using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Foo.DataAccessLayer;
using Foo.DataAccessLayer.DataTypes;

using Foo.WorkspaceMgr.Closers;
using Foo.WorkspaceMgr.Hiders;
using Foo.WorkspaceMgr.Launchers;
using System.Reflection;

namespace Foo.WorkspaceMgr
{
    public class WorkspaceMgr : IWorkspaceMgr
    {
        #region IWorkspaceMgr Members

        /// <summary>
        /// Responsible for Launching a single artifact                         // ToDo: - CHECK RAT if Artifact is already running
        /// </summary>                                                          // ToDo: - Test IEXPLORER LAUNCHER
        /// <param name="artifactItem">artifact to launch</param>               // ToDo: - Figgure out what to do in Error State
        /// <returns>true if successful, false otherwise</returns>                      
        public bool LaunchArtifact(ArtifactItem artifactItem)
        {

            AssemblyName assemblyName = new AssemblyName("Microsoft.Office.Interop.Access, Version=11.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c");
            Assembly assembly = Assembly.Load(assemblyName);


            //if (artifactItem.IsValid && artifactItem.IsValidFileIntegrity)
            if (artifactItem.IsLocationValid)
            {                
                // Step One - Create the Launcher Obj
                ILaunch launcher = WorkspaceTypeHelpers.CreateLauncherObj(artifactItem);
                if (launcher == null)
                    return false;

                // Step Two - Query if Launching for this Artifact is supported
                FuncDepBoolType retVal = launcher.IQueryLaunch(artifactItem.Location);

                // Step Three - launch it if supported
                if (retVal == FuncDepBoolType.Success)
                {
                    retVal = launcher.ILaunch(artifactItem.Location);
                }
                else
                {
                    // * Log error or something and return otherwise * To Do
                    return false;
                }

                // Step Four - if success signal to the db the artifact was launched
                if (retVal == FuncDepBoolType.Success)
                {
                    Data.Artifacts.ArtifactWasLaunched(artifactItem);
                }

                return (retVal == FuncDepBoolType.Success);
            }
            return false;      
        }

        /// <summary>
        /// Responsible for Closing a single artifact                           // ToDo: - CHECK RAT if Artifact is running, if so Get Proccess that it is running in!!! ----
        /// </summary>                                                          // ToDo: - Test Office, Generic, Notepad, IExplore Closers
        /// <param name="artifactItem">artifact to close</param>                // ToDo: - Figgure out what to do in Error State
        /// <returns>true if successful, false otherwise</returns>
        public bool CloseArtifact(ArtifactItem artifactItem)
        {
            if (artifactItem.IsValid && artifactItem.IsValidFileIntegrity)
            {
                // Step One - Create the Closer Obj
                IClose closer = WorkspaceTypeHelpers.CreateCloserObj(artifactItem);
                if (closer == null)
                    return false;

                // Step Two - Query if Closing for this Artifact is possible
                FuncDepBoolType retVal = closer.IQueryClose(artifactItem.Location);

                // Step Three - close it if supported               
                if (retVal == FuncDepBoolType.Success)
                {
                    retVal = closer.IClose(artifactItem.Location);
                }
                else
                {
                    // * Log error or something and return otherwise * To Do
                    return false;
                }
                
                return (retVal == FuncDepBoolType.Success);
            }
            return false;
        }

        /// <summary>
        /// Responsible for Hiding or showing a single artifact                 // ToDo: - CHECK RAT if Artifact is running, if so Get Proccess that it is running in!!! ----
        /// </summary>                                                          // ToDo: - Test Office, Generic, Notepad, IExplore Hiders
        /// <param name="artifactItem">artifact to hide</param>                 // ToDo: - Figgure out what to do in Error State
        /// <param name="bShow">true to show, false to hide artifact</param>
        /// <returns>true if successful, false otherwise</returns>
        public bool HideShowArtifact(ArtifactItem artifactItem, bool bShow)
        {
            if (artifactItem.IsValid && artifactItem.IsValidFileIntegrity)
            {
                // Step One - Create the ShowNHider Obj
                IShowNHide ShowHider = WorkspaceTypeHelpers.CreateShowNHiderObj(artifactItem);
                if (ShowHider == null)
                    return false;

                // Step Two - Query if Hiding or Showing is available for this Artifact
                FuncDepBoolType retVal = FuncDepBoolType.Failed;
                if (bShow)
                    retVal = ShowHider.IQueryShow(artifactItem.Location);
                else
                    retVal = ShowHider.IQueryHide(artifactItem.Location);                

                // Step Three - Show or Hide it if supported               
                if (retVal == FuncDepBoolType.Success)
                {
                    if(bShow)
                       retVal = ShowHider.IShow(artifactItem.Location);
                    else
                       retVal = ShowHider.IHide(artifactItem.Location);
                }
                else
                {
                    // * Log error or something and return otherwise * To Do
                    return false;
                }

                return (retVal == FuncDepBoolType.Success);                
            }
            return false;
        }

        /// <summary>                                                                       // ToDo: - 
        /// Launches a Workspace. When for some reason an artifact location
        /// is not available to launch we keep track of it and display it to the
        /// user - however, we don't stop. we try to launch as many artifacts as
        /// we can.
        /// ---------------------------------------------------------------------
        /// There are a few steps we have to do in order to successfully launch:
        /// 1) Make sure all files that have the same file name are not launched together
        /// 2) we must wait a little after each file to make sure that they can be resolved
        /// 
        /// </summary>
        /// <param name="WorkspaceName">Name of Workspace to launch artifacts for</param>
        /// <returns>true if 1 or more artifacts were launched, false otherwise</returns>
        public bool LaunchWorkspace(string WorkspaceName)
        {
            // Step One - First Get all the Artifacts by Name
            ArtifactItem[] artifacts = Data.Artifacts.GetAllArtifactsForWorkspace(WorkspaceName, SortOrderForArtifacts.Descending);            
            if (!DataTypeValidation.IsEmptyArtifactItemGroup(artifacts))
            {     
           
                // Let's get the optimal Indexes for all the file artifacts
                int[] optimalIndexes;
                HelperFunc.IndexOptimizationQuality quality;
                quality = HelperFunc.OptimalLaunchIndexesForFileArtifacts(artifacts, out optimalIndexes);                 

                ////
                // Launch the file Artifacts according to their optimal indexes
                ////
                foreach (int optIndex in optimalIndexes)
                {
                    // Launch file artifact                    
                    LaunchArtifact(artifacts[optIndex]);

                    // depending on the quality of indexes sleep accordingly
                    int nSleepTime = HelperFunc.GetSleepTimeForQuality(quality);                    
                    
                    // Sleep Now before launching again
                    System.Threading.Thread.Sleep(nSleepTime);
                }

                ////
                // Launch the url Artifacts according to their optimal indexes
                ////
                foreach (ArtifactItem artifact in artifacts)
                {
                    if (artifact.IsUrl)
                    {                        
                        LaunchArtifact(artifact);
                        System.Threading.Thread.Sleep(HelperFunc.DEFAULT_LAUNCH_SLEEP_TIME);
                    }
                }
                
                // Signal the Workspace as Launched
                Data.Workspace.WorkspaceWasLaunched(WorkspaceName);

                // Set it to this Workspace 'State'
                Data.State.SetCurrentWorkspaceName(WorkspaceName);
            }
            return false;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="WorkspaceName">Name of Workspace to close artifacts for</param>
        /// <returns></returns>
        public bool CloseWorkspace(string WorkspaceName)
        {
            ArtifactItem[] artifacts = Data.Artifacts.GetAllArtifactsForWorkspace(WorkspaceName, SortOrderForArtifacts.Ascending);
            if (!DataTypeValidation.IsEmptyArtifactItemGroup(artifacts))
            {
                foreach (ArtifactItem artifact in artifacts)
                {
                    CloseArtifact(artifact);

                    // Sleep a little
                    System.Threading.Thread.Sleep(HelperFunc.DEFAULT_CLOSE_SLEEP_TIME);
                }

                // Clear Workspace 'State'
                Data.State.ClearCurrentWorkspaceName();
            }
            return false;
        }
        
        /// <summary>
        /// 
        /// </summary>
        /// <param name="WorkspaceName"></param>
        /// <param name="bShow">true to show, false to hide artifact</param>
        /// <returns></returns>
        public bool HideShowWorkspace(string WorkspaceName, bool bShow)
        {
            ArtifactItem[] artifacts = Data.Artifacts.GetAllArtifactsForWorkspace(WorkspaceName, SortOrderForArtifacts.Ascending);

            if (!DataTypeValidation.IsEmptyArtifactItemGroup(artifacts))
            {
                foreach (ArtifactItem artifact in artifacts)
                {
                    HideShowArtifact(artifact, bShow);

                    // Sleep a little
                    System.Threading.Thread.Sleep(HelperFunc.DEFAULT_SHOWNHIDE_SLEEP_TIME);
                }
            }
            return false;
        }

        #endregion
    }
}
