using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Foo.AddIn.Common;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Drawing;

// Ignore 'Ambiguity' warning message, seems like no way around those
#pragma warning disable 0467

namespace Foo.Addin.Office
{
    public class Access_Workspace : IWorkspace
    {
        public const string Access_ProgId = "Access.Application";

        public FuncRetVal Launch(string strArtifactLocation, int WindowHeight, int WindowWidth, int WindowTop, int WindowLeft)
        {
            FuncRetVal retVal = new FuncRetVal();
            if (!Validate.IsValidArtifactLocation(strArtifactLocation, ref retVal))
                return retVal;

            try
            {
                Microsoft.Office.Interop.Access.Application app = new Microsoft.Office.Interop.Access.Application();
                app.Visible = true;

                // Must test the following here:
                // - open both .mdb and .adp (access project files with this)
                // - how does this behave when db is password protected?
                app.OpenCurrentDatabase(strArtifactLocation, true, "");

                // ToDo: Check if a new process got created? / or if hWnd exists???
                //       - Also PERFORM Window Positioning
                retVal.Type = FuncRetValEnum.Action_Succeeded;
            }
            catch (Exception e)
            {
                retVal.Message = e.Message;
                retVal.Type = FuncRetValEnum.ErrorThrown;
            }
            return retVal;
        }

        public FuncRetVal Launch(string strArtifactLocation)
        {
            FuncRetVal retVal = new FuncRetVal();
            if (!Validate.IsValidArtifactLocation(strArtifactLocation, ref retVal))
                return retVal;

            try
            {
                Microsoft.Office.Interop.Access.Application app = new Microsoft.Office.Interop.Access.Application();
                app.Visible = true;

                // Must test the following here:
                // - open both .mdb and .adp (access project files with this)
                // - how does this behave when db is password protected?
                app.OpenCurrentDatabase(strArtifactLocation, true, "");                

                // ToDo: Check if a new process got created? / or if hWnd exists???
                retVal.Type = FuncRetValEnum.Action_Succeeded;
            }
            catch (Exception e)
            {
                retVal.Message = e.Message;
                retVal.Type = FuncRetValEnum.ErrorThrown;
            }
            return retVal;
        }

        public FuncRetVal Show(string strArtifactLocation)
        {
            FuncRetVal retVal = new FuncRetVal();
            if (!Validate.IsValidArtifactLocation(strArtifactLocation, ref retVal))
                return retVal;

            try
            {
                var RunningAccessApps = Functions.GetRunningObjectsOfType<Microsoft.Office.Interop.Access.Application>();
                foreach (Microsoft.Office.Interop.Access.Application app in RunningAccessApps)
                {
                    if (app.CurrentProject.FullName.ToLower() == strArtifactLocation.ToLower())
                    {
                        IntPtr hWnd = (IntPtr)app.hWndAccessApp();
                        if (!Functions.IsWindowVisible(hWnd))
                        {
                            Functions.ShowWindow(hWnd, Functions.FuncEnum.WindowAction.SW_SHOW);
                            retVal.Type = FuncRetValEnum.Action_Succeeded;
                            return retVal;
                        }
                        else
                        {
                            retVal.Type = FuncRetValEnum.NoAction_Needed;
                            return retVal;
                        }
                    }
                }
                retVal.Type = FuncRetValEnum.ArtifactUnavailable;
            }
            catch (Exception e)
            {
                retVal.Message = e.Message;
                retVal.Type = FuncRetValEnum.ErrorThrown;
            }
            return retVal;
        }

        public FuncRetVal Hide(string strArtifactLocation)
        {
            FuncRetVal retVal = new FuncRetVal();
            if (!Validate.IsValidArtifactLocation(strArtifactLocation, ref retVal))
                return retVal;

            try
            {
                var RunningAccessApps = Functions.GetRunningObjectsOfType<Microsoft.Office.Interop.Access.Application>();
                foreach (Microsoft.Office.Interop.Access.Application app in RunningAccessApps)
                {
                    if (app.CurrentProject.FullName.ToLower() == strArtifactLocation.ToLower())
                    {
                        IntPtr hWnd = (IntPtr)app.hWndAccessApp();
                        if (Functions.IsWindowVisible(hWnd))
                        {
                            Functions.ShowWindow(hWnd, Functions.FuncEnum.WindowAction.SW_HIDE);
                            retVal.Type = FuncRetValEnum.Action_Succeeded;
                            return retVal;
                        }                                                
                        else
                        {
                            retVal.Type = FuncRetValEnum.NoAction_Needed;
                            return retVal;
                        }
                    }
                }
                retVal.Type = FuncRetValEnum.ArtifactUnavailable;
            }
            catch (Exception e)
            {
                retVal.Message = e.Message;
                retVal.Type = FuncRetValEnum.ErrorThrown;
            }
            return retVal;
        }
        
        public FuncRetVal QueryClose(string strArtifactLocation)
        {
            FuncRetVal retVal = new FuncRetVal();
            if (!Validate.IsValidArtifactLocation(strArtifactLocation, ref retVal))
                return retVal;

            try
            {
                var RunningAccessApps = Functions.GetRunningObjectsOfType<Microsoft.Office.Interop.Access.Application>();
                foreach (Microsoft.Office.Interop.Access.Application app in RunningAccessApps)
                {
                    if (app.CurrentProject.FullName.ToLower() == strArtifactLocation.ToLower())
                    {
                        IntPtr hWnd = (IntPtr) app.hWndAccessApp();
                        if (Functions.SendMessage(hWnd, Functions.FuncEnum.WindowMessage.WM_QUERYENDSESSION, IntPtr.Zero, IntPtr.Zero) != 0)
                        {
                            retVal.Type = FuncRetValEnum.Action_Succeeded;
                            return retVal;
                        }
                        else
                        {
                            retVal.Type = FuncRetValEnum.Action_Failed;
                            return retVal;
                        }
                    }
                }

                retVal.Type = FuncRetValEnum.ArtifactUnavailable;
            }
            catch (Exception e)
            {
                retVal.Message = e.Message;
                retVal.Type = FuncRetValEnum.ErrorThrown;
            }
            return retVal;
        }

        public FuncRetVal Close(string strArtifactLocation, bool bAutoSaveArtifact, out int WindowHeight, out int WindowWidth, out int WindowTop, out int WindowLeft)
        {
            FuncRetVal retVal = new FuncRetVal();
            WindowTop = 0;
            WindowLeft = 0;
            WindowWidth = 0;
            WindowHeight = 0;

            if (!Validate.IsValidArtifactLocation(strArtifactLocation, ref retVal))
                return retVal;

            try
            {
                var RunningAccessApps = Functions.GetRunningObjectsOfType<Microsoft.Office.Interop.Access.Application>();
                foreach (Microsoft.Office.Interop.Access.Application app in RunningAccessApps)
                {
                    if (app.CurrentProject.FullName.ToLower() == strArtifactLocation.ToLower())
                    {
                        // Get Handle and Process
                        IntPtr hWnd = (IntPtr)app.hWndAccessApp();
                        Process process = Functions.GetProcessFromHandle((IntPtr)hWnd);

                        // Get the Window properties                        
                        Rectangle rect = Functions.GetWindowRect(hWnd);
                        WindowHeight = rect.Height;
                        WindowWidth = rect.Width;
                        WindowLeft = rect.Left;
                        WindowTop = rect.Top;

                        // Close the database
                        //app.CloseCurrentDatabase();                        
                        if (bAutoSaveArtifact)
                            app.Quit(Microsoft.Office.Interop.Access.AcQuitOption.acQuitSaveAll);
                        else
                            app.Quit(Microsoft.Office.Interop.Access.AcQuitOption.acQuitSaveNone);
                        Marshal.FinalReleaseComObject(app); // force clean-up

                        // Kill the process                    
                        process.Kill();

                        retVal.Type = FuncRetValEnum.Action_Succeeded;
                        return retVal;
                    }
                }

                retVal.Type = FuncRetValEnum.ArtifactUnavailable;
            }
            catch (Exception e)
            {
                retVal.Message = e.Message;
                retVal.Type = FuncRetValEnum.ErrorThrown;
            }
            return retVal;
        }

        public FuncRetVal Close(string strArtifactLocation, bool bAutoSaveArtifact)
        {
            FuncRetVal retVal = new FuncRetVal();
            if (!Validate.IsValidArtifactLocation(strArtifactLocation, ref retVal))
                return retVal;

            try
            {
                var RunningAccessApps = Functions.GetRunningObjectsOfType<Microsoft.Office.Interop.Access.Application>();
                foreach (Microsoft.Office.Interop.Access.Application app in RunningAccessApps)
                {
                    if (app.CurrentProject.FullName.ToLower() == strArtifactLocation.ToLower())
                    {
                        // Get Handle and Process
                        IntPtr hWnd = (IntPtr)app.hWndAccessApp();
                        Process process = Functions.GetProcessFromHandle((IntPtr)hWnd);

                        // Close the database
                        //app.CloseCurrentDatabase();
                        if(bAutoSaveArtifact)
                            app.Quit(Microsoft.Office.Interop.Access.AcQuitOption.acQuitSaveAll);
                        else
                            app.Quit(Microsoft.Office.Interop.Access.AcQuitOption.acQuitSaveNone);
                        Marshal.FinalReleaseComObject(app); // force clean-up

                        // Kill the process                    
                        process.Kill();

                        retVal.Type = FuncRetValEnum.Action_Succeeded;
                        return retVal;
                    }
                }

                retVal.Type = FuncRetValEnum.ArtifactUnavailable;
            }
            catch (Exception e)
            {
                retVal.Message = e.Message;
                retVal.Type = FuncRetValEnum.ErrorThrown;
            }
            return retVal;
        }

        public FuncRetVal Close(string strArtifactLocation)
        {
            FuncRetVal retVal = new FuncRetVal();
            if (!Validate.IsValidArtifactLocation(strArtifactLocation, ref retVal))
                return retVal;

            try
            {
                var RunningAccessApps = Functions.GetRunningObjectsOfType<Microsoft.Office.Interop.Access.Application>();
                foreach (Microsoft.Office.Interop.Access.Application app in RunningAccessApps)
                {
                    if (app.CurrentProject.FullName.ToLower() == strArtifactLocation.ToLower())
                    {
                        // Get Handle and Process
                        IntPtr hWnd = (IntPtr)app.hWndAccessApp();
                        Process process = Functions.GetProcessFromHandle((IntPtr)hWnd);

                        // Close the database
                        //app.CloseCurrentDatabase();
                        app.Quit(Microsoft.Office.Interop.Access.AcQuitOption.acQuitSaveAll);
                        Marshal.FinalReleaseComObject(app); // force clean-up

                        // Kill the process                    
                        process.Kill();

                        retVal.Type = FuncRetValEnum.Action_Succeeded;
                        return retVal;
                    }
                }

                retVal.Type = FuncRetValEnum.ArtifactUnavailable;
            }
            catch (Exception e)
            {
                retVal.Message = e.Message;
                retVal.Type = FuncRetValEnum.ErrorThrown;
            }
            return retVal;
        }

    }
}
