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

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

namespace Foo.Addin.Office
{
    public class Visio_Workspace : IWorkspace
    {
        public const string Visio_ProgId = "Visio.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.Visio.Application app = null;
                app = new Microsoft.Office.Interop.Visio.Application();

                // Mark the Application as visible
                app.Visible = true;

                app.Documents.Open(strArtifactLocation);

                // ToDo: Check if a new process got created? / or if hWnd exists???
                //       - Also PERFORM Window Positioning
                app.ActiveWindow.SetWindowRect(WindowLeft, WindowTop, WindowWidth, WindowHeight);

                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.Visio.Application app = null;
                app = new Microsoft.Office.Interop.Visio.Application();

                // Mark the Application as visible
                app.Visible = true;

                app.Documents.Open(strArtifactLocation);

                // Keep Track of all our Excel Instances -- not needed in visio?
                ///WorkspaceState.Launched_ExcelInstances.Add(app);

                retVal.Type = FuncRetValEnum.Action_Succeeded;
              
                //if (!String.IsNullOrEmpty(strArtifactLocation) && (strArtifactLocation.Length > 3))
                //{                
                //    Process.Start(strArtifactLocation);                               
                //}
                //return FuncDepBoolType.ParametersInvalid;                 
            }
            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 RunningVisioDocs = Functions.GetRunningObjectsOfType<Microsoft.Office.Interop.Visio.Document>();
                foreach (Microsoft.Office.Interop.Visio.Document doc in RunningVisioDocs)
                {
                    if (doc.FullName.ToLower() == strArtifactLocation.ToLower())
                    {
                        // TO DO -  (doc.Application.Documents.Count == 1); not working, why?!?!? odd
                        bool bIsTrue = (doc.Application.Documents.Count == 1); // not working, why?!?!? odd
                        //bool bIsTheOnlyDocumentInApp = true;

                        if (!doc.Application.Visible) // && bIsTheOnlyDocumentInApp)
                        {
                            doc.Application.Visible = true;
                            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 RunningVisioDocs = Functions.GetRunningObjectsOfType<Microsoft.Office.Interop.Visio.Document>();
                foreach (Microsoft.Office.Interop.Visio.Document doc in RunningVisioDocs)
                {
                    if (doc.FullName.ToLower() == strArtifactLocation.ToLower())
                    {                        
                        // TO DO -  (doc.Application.Documents.Count == 1); not working, why?!?!? odd
                        bool bIsTrue = (doc.Application.Documents.Count == 1); // not working, why?!?!? odd
                        //bool bIsTheOnlyDocumentInApp = true;

                        if (doc.Application.Visible) // && bIsTheOnlyDocumentInApp)
                        {
                            doc.Application.Visible = false;
                            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 RunningVisioDocs = Functions.GetRunningObjectsOfType<Microsoft.Office.Interop.Visio.Document>();
                foreach (Microsoft.Office.Interop.Visio.Document doc in RunningVisioDocs)
                {
                    if (doc.FullName.ToLower() == strArtifactLocation.ToLower())
                    {                      
                        if (doc.Saved)
                        {
                            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 RunningVisioDocs = Functions.GetRunningObjectsOfType<Microsoft.Office.Interop.Visio.Document>();
                foreach (Microsoft.Office.Interop.Visio.Document doc in RunningVisioDocs)
                {
                    if (doc.FullName.ToLower() == strArtifactLocation.ToLower())
                    {
                        if (bAutoSaveArtifact)
                            doc.Save();

                        var app = doc.Application;

                        // Get the Window properties
                        app.ActiveWindow.GetWindowRect(out WindowLeft, out WindowTop, out WindowWidth, out WindowHeight);
                        
                        doc.Close();
                        Marshal.FinalReleaseComObject(doc); // Force Clean-up

                        if (app.Documents.Count == 0)
                        {
                            app.Quit();
                            Marshal.FinalReleaseComObject(app); // force clean-up
                        }
                    }
                }
                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 RunningVisioDocs = Functions.GetRunningObjectsOfType<Microsoft.Office.Interop.Visio.Document>();
                foreach (Microsoft.Office.Interop.Visio.Document doc in RunningVisioDocs)
                {
                    if (doc.FullName.ToLower() == strArtifactLocation.ToLower())
                    {
                        if(bAutoSaveArtifact)
                           doc.Save();

                        var app = doc.Application;

                        doc.Close();
                        Marshal.FinalReleaseComObject(doc); // Force Clean-up

                        if (app.Documents.Count == 0)
                        {
                            app.Quit();
                            Marshal.FinalReleaseComObject(app); // force clean-up
                        }
                    }
                }
                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 RunningVisioDocs = Functions.GetRunningObjectsOfType<Microsoft.Office.Interop.Visio.Document>();
                foreach (Microsoft.Office.Interop.Visio.Document doc in RunningVisioDocs)
                {
                    if (doc.FullName.ToLower() == strArtifactLocation.ToLower())
                    {
                        doc.Save();

                        var app = doc.Application;

                        doc.Close();
                        Marshal.FinalReleaseComObject(doc); // Force Clean-up

                        if (app.Documents.Count == 0)
                        {
                            app.Quit();
                            Marshal.FinalReleaseComObject(app); // force clean-up
                        }
                    }
                }
                retVal.Type = FuncRetValEnum.ArtifactUnavailable;
            }
            catch (Exception e)
            {
                retVal.Message = e.Message;
                retVal.Type = FuncRetValEnum.ErrorThrown;
            }
            return retVal;             
        }

    }
}
