using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using Foo.Settings;
using Foo.Platform.Win32;
using Foo.DataAccessLayer.DataTypes;
using Foo.WorkspaceMgr.Hiders;
using Foo.WorkspaceMgr.Closers;
using Foo.WorkspaceMgr.Launchers;

namespace Foo.WorkspaceMgr
{
    /// <summary>
    /// Allows us to extend functionallity by creating our own
    /// Custom Types to be used in certain scenarios
    /// </summary>
    internal enum CustomStateChangingTypes
    {
        LaunchGenericUrl
    }

    /// <summary>
    /// Useful for StateChanger Returns where we 
    /// need more information on failures 
    /// </summary>
    public enum FuncDepBoolType
    {        
        Success,
        Failed,
        ParametersInvalid,
        ArtifactLocationUnavailable,
        FunctionallityNotSupported,
        ErrorThrown
    }

    /// <summary>
    /// Use this to request the proper state
    /// Changing Object
    /// </summary>
    public enum StateChangerReqType
    {
        Launcher,
        ShowNHider,
        Closer
    }

    /// <summary>
    /// Class for useful Workspace Type Helpers
    /// </summary>
    internal static class WorkspaceTypeHelpers
    {
        private static configuration _configuration = null;

        static WorkspaceTypeHelpers()
        {
            OoganizerSettingsAcc accessor = new OoganizerSettingsAcc();
            _configuration = accessor.ReadConfigXMLFile();
        }

        #region Internal Object Creator Functions (Call these in this assembly)
        
        /// <summary>
        /// Creates a Launcher Object from an artifact Item
        /// </summary>
        /// <param name="artifactItem">valid artifact to create a launcher for</param>
        /// <returns>object or null</returns>
        internal static ILaunch CreateLauncherObj(ArtifactItem artifactItem)
        {
            if (artifactItem.IsUrl)
            {
                return CreateLauncherObj(CustomStateChangingTypes.LaunchGenericUrl.ToString());
            }
            else if (artifactItem.IsFile)
            {
                string strRegisteredProcessExe = Win32_WrapperFunc.GetRegisteredExeForFile(artifactItem.Location);
                if (!String.IsNullOrEmpty(strRegisteredProcessExe))
                    return CreateLauncherObj(strRegisteredProcessExe);
                //return CreateLauncherObj(LauncherGenericType.LaunchGenericFile);
            }
            return null;
        }

        /// <summary>
        /// Creates a Hider Object from an artifact Item
        /// </summary>
        /// <param name="strProcessName">name for process to create object for</param>
        /// <returns>object or null</returns>
        internal static IShowNHide CreateShowNHiderObj(ArtifactItem artifactItem)   // TO DO: We can check the RAT which Process the artifact was launched in!!
        {
            if (artifactItem.IsUrl)
            {
                // To Do: Query the RAT for the process this artifact is in, then call
                //        the object creator function for the correct process
                return null;                
            }
            else if (artifactItem.IsFile)
            {
                string strRegisteredProcessExe = Win32_WrapperFunc.GetRegisteredExeForFile(artifactItem.Location);
                if (!String.IsNullOrEmpty(strRegisteredProcessExe))
                    return CreateShowNHiderObj(strRegisteredProcessExe);
            }
            return null;
        }

        /// <summary>
        /// Creates a Closer Object from an artifact Item
        /// </summary>
        /// <param name="artifactItem">valid artifact to a closer for</param>
        /// <returns>object or null</returns>
        internal static IClose CreateCloserObj(ArtifactItem artifactItem)     // TO DO: We can check the RAT which Process the artifact was launched in!!
        {
            if (artifactItem.IsUrl)
            {
                // To Do: Query the RAT for the process this artifact is in, then call
                //        the object creator function for the correct process
                return null;
            }
            else if (artifactItem.IsFile)
            {
                string strRegisteredProcessExe = Win32_WrapperFunc.GetRegisteredExeForFile(artifactItem.Location);
                if (!String.IsNullOrEmpty(strRegisteredProcessExe))
                    return CreateCloserObj(strRegisteredProcessExe);
            }
            return null;
        }

        #endregion

        #region Private Object Creator Helper Functions

        /// <summary>
        /// Creates a Closer Object
        /// </summary>
        /// <param name="strProcessName">name for process to create object for</param>
        /// <returns>object or null</returns>
        private static IClose CreateCloserObj(string ProcessNameOrCustomType)
        {
            object o = CreateStateChangerObject(StateChangerReqType.Closer, ProcessNameOrCustomType);
            if (IsObjectOfType(StateChangerReqType.Closer, o))
                return (o as IClose);
            else
                return null;
        }

        /// <summary>
        /// Creates a Hider Object
        /// </summary>
        /// <param name="strProcessName">name for process to create object for</param>
        /// <returns>object or null</returns>
        private static IShowNHide CreateShowNHiderObj(string ProcessNameOrCustomType)
        {
            object o = CreateStateChangerObject(StateChangerReqType.ShowNHider, ProcessNameOrCustomType);
            if (IsObjectOfType(StateChangerReqType.ShowNHider, o))
                return (o as IShowNHide);
            else
                return null;
        }

        /// <summary>
        /// Creates a Launcher Object
        /// </summary>
        /// <param name="type">type of Launcher you want to create</param>
        /// <returns>object or null</returns>
        private static ILaunch CreateLauncherObj(string ProcessNameOrCustomType)
        {
            object o = CreateStateChangerObject(StateChangerReqType.Launcher, ProcessNameOrCustomType);
            if (IsObjectOfType(StateChangerReqType.Launcher, o))
                return (o as ILaunch);
            else
                return null;
        }

        /// <summary>
        /// Useful for quick Interface Type checking of StateChangers
        /// </summary>
        /// <param name="reqType">A StateChangerRequestTyp</param>
        /// <param name="o">a stateChanger Object</param>
        /// <returns>true if object is of that Type</returns>
        private static bool IsObjectOfType(StateChangerReqType reqType, object o)
        {
            if (o != null)
            {
                switch (reqType)
                {
                    case StateChangerReqType.Launcher:
                        return (o is ILaunch);

                    case StateChangerReqType.ShowNHider:
                        return (o is IShowNHide);

                    case StateChangerReqType.Closer:
                        return (o is IClose);
                }
            }
            return false;
        }

        #endregion

        #region Main Object Factory Function (All calls ultimately end up here)

        /// <summary>
        /// Function is responsible for create the StateChanging Objects that we
        /// need for the system. It will either be hardcoded in or be reading from
        /// the settings file to know what object to create
        /// </summary>
        /// <param name="reqType">A StateChangerRequestType</param>
        /// <param name="ProcessName">the name of the process to create it for</param>
        /// <returns>an object of the correct type, the caller must then cast it</returns>
        private static object CreateStateChangerObject(StateChangerReqType reqType, string ProcessNameOrCustomType)
        {
            if (!String.IsNullOrEmpty(ProcessNameOrCustomType))
            {
                ////
                // First Step - Create any Custom Types
                ////
                switch (ProcessNameOrCustomType)
                {                 
                    case "LaunchGenericUrl":
                    {
                        if (reqType == StateChangerReqType.Launcher)
                            return new Launchers.Launcher_Web();
                    }
                    break;
                }

                ////
                // Second Step - Read thru the Configuration and create the corresponding
                //               object as the Configuration says we should use
                ////
                foreach (ButtonHookSettings.ProcessName processObj in _configuration.ButtonHook.AllowedProcessNames.ProcessNames)
                {
                    
                    if (processObj.ProcessExe == ProcessNameOrCustomType.ToUpper())
                    {
                        switch (reqType)
                        {
                            case StateChangerReqType.Launcher:
                                switch (processObj.Launcher.ToUpper())
                                {
                                    case "WEB":
                                        return new Launcher_Web();

                                    case "SHELL":
                                        return new Launcher_Shell();

                                    case "EXCEL":
                                        return new Launcher_Excel();

                                    case "VISIO":
                                        return new Launcher_Visio();

                                    default:
                                        return new Launcher_Generic();
                                }

                            case StateChangerReqType.Closer:
                                switch (processObj.Closer.ToUpper())
                                {
                                    case "IE":
                                        return new Closer_IE();

                                    case "OFFICE":
                                        return new Closer_Office();

                                    default:
                                        return new Closer_Generic();
                                }

                            case StateChangerReqType.ShowNHider:
                                switch (processObj.ShowHider.ToUpper())
                                {
                                    case "OFFICE":
                                        return new ShowNHide_Office();

                                    default:
                                        return new ShowNHide_Generic();
                                }

                        }
                    }
                }
            }     
            return null;
        }

        #endregion
    }
}
