using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Runtime.InteropServices;
using System.Drawing;
using System.Reflection;
using SnapshotImage = System.Drawing.Image;

// Ooganizer namespaces
using Foo.ClientServices.ButtonWPForm.ButtonFormPages;
using Foo.Platform;
using Foo.Platform.Win32;
using Foo.Platform.ErrorReporting;
using Foo.Platform.Interacters;
using System.Windows.Interop;

namespace Foo.ClientServices.ButtonWPForm
{
    /// <summary>
    /// Interaction logic for ButtonWindow Form
    /// </summary>
    [ComVisible(false)]
    public partial class ButtonForm : Window
    {
        ////
        // Public Properties
        ////
        public IntPtr HookedWindow { get { return _hHookedWnd; } set { _hHookedWnd = value; } }         // Passed in by FormMgr
        public System.Drawing.Image SnapShot { get { return _SnapShot; } set { _SnapShot = value; } }   // Passed in by FormMgr
        //public Artifact Artifact { get { return _Artifact; } }
        //public string ArtifactTitle { get { return _ArtifactTitle; } }
        //public string ArtifactLocation { get { return _ArtifactLocation; } }
        //public string CurrentWorkspaceName { get { return _CurrentWorkspaceName; } }

        ////
        // Private Member Variables
        ////
        private IntPtr _hHookedWnd = IntPtr.Zero;         
        private System.Drawing.Image _SnapShot = null;
        private bool _PerformanceCache = false;
        private static ButtonForm s_PerfCacheButtonFormObj = null;
        private bool _PerfCacheLoadedHidden = false;        
        //private Artifact _Artifact;
        //private string _ArtifactTitle;
        //private string _ArtifactLocation;
        //private string _CurrentWorkspaceName;

        ////
        // ButtonFormPages
        ////
        IButtonFormPage[] m_ButtonFormPages = new IButtonFormPage[1];

        // Declare the Log4net Variable        
        private static log4net.ILog Log = Logger.GetLog4NetInterface(MethodBase.GetCurrentMethod().DeclaringType);

        /// <summary>
        /// Construct WPF ButtonForm :)
        /// </summary>
        public ButtonForm()
        {            
            InitializeComponent();
        }

        /// <summary>
        /// Construct WPF ButtonForm (Performance Cache)
        /// </summary>
        public ButtonForm(bool bPerformanceCache)
        {
            if (bPerformanceCache && (s_PerfCacheButtonFormObj == null))
            {
                _PerformanceCache = bPerformanceCache;
                s_PerfCacheButtonFormObj = this;                
            }

            InitializeComponent();
        }

        /// <summary>
        /// As part of Performance Caching (load one instance of this form
        /// hidden and not visible to the user (called by FormMgr) ~also
        /// allows to hide and existing one
        /// ~Should only be called by FormMgr when creating the first object
        /// </summary>
        public void LoadHideButtonFormPerfCache()
        {
            if (!_PerfCacheLoadedHidden && _PerformanceCache && (s_PerfCacheButtonFormObj != null))
            {
                s_PerfCacheButtonFormObj.Opacity = 0;
                s_PerfCacheButtonFormObj.WindowState = WindowState.Minimized;
                s_PerfCacheButtonFormObj.ShowInTaskbar = false;
                s_PerfCacheButtonFormObj.Show();
                s_PerfCacheButtonFormObj.Hide();
                _PerfCacheLoadedHidden = true;
            }
        }

        /// <summary>
        /// Window Load Event. We want all object loading to happen in the Load Event,
        /// because we construct the WPFForm and show it right away, so this is called right at
        /// start up, so put all the object loading in here to be cleaner and simplify FormObject Creator
        /// </summary>        
        private void OnLoad(object sender, RoutedEventArgs args)
        {
            try
            {
                if (_PerformanceCache && (this == s_PerfCacheButtonFormObj)) // Preload child pages
                {
                    PreloadAllChildPages();

                    // Add Message Hook for performance WPForm * To make sure it is always invisible *
                    HwndSource source = HwndSource.FromHwnd(new WindowInteropHelper(this).Handle);
                    source.AddHook(new HwndSourceHook(MessageHook)); 
                }
                else if (!_PerformanceCache && (HookedWindow != IntPtr.Zero) && (this != s_PerfCacheButtonFormObj))
                {
                    ////
                    // Resolve the Window and set the properties accordingly, 
                    // our child pages depend on this information
                    ////
                    //ResolverDispatch resolver = new ResolverDispatch();
                    //ArtifactGroup artifacts = resolver.GetArtifacts(HookedWindow);

                    //if (artifacts.Length > 0)
                    //{
                    //    _Artifact = artifacts.GetPrimary;
                    //    _ArtifactTitle = _Artifact.Name;
                    //    _ArtifactLocation = _Artifact.Location;

                    //    // Workspace
                    //    _CurrentWorkspaceName = SrvrCommon.GetCurrentWorkspaceName();

                    //    // Now Load the Page
                    //    LoadPageAccordingToState();
                    //}
                    //else
                    //{
                    //    // Somemething went wrong Resolving
                    //    UserError.Show("Document not Found", "Failed to accurately find the document for the Window");
                    //    Close(); //~imp, we must close this Form
                    //}
                }
            }
            catch (Exception e)
            {
                Log.Error(string.Format("{0}() - A fatal error occured loading ButtonForm", MethodBase.GetCurrentMethod().Name), e);
                Close(); //~imp, we must close this Form
            }
        }

        /// <summary>
        /// This Message Hook is for the Hidden WPForm that we use for better performance,
        /// We want to make sure that it is never displayed *It can occur that explore can show it, without this*
        /// </summary>       
        private IntPtr MessageHook(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
        {
            // force opacity at all times
            if (Opacity == 1.0)
                Opacity = 0.0;

            // force minimized at all times
            if (WindowState != WindowState.Minimized)
                WindowState = WindowState.Minimized;

            // force Not to be seen in taskbar
            if (ShowInTaskbar == true)
                ShowInTaskbar = false;

            return System.IntPtr.Zero;
        }

        /// <summary>
        /// For Performance, we need to preload all Child Pages
        /// </summary>
        private void PreloadAllChildPages()
        {
            m_ButtonFormPages[0] = (IButtonFormPage) new Page_AddEdit();
            m_ButtonFormPages[0].ParentWPFContainer = this;
        }

        /// <summary>
        /// Show different pages depending on the state we are in. (Currently only 1 state)
        /// </summary>
        private void LoadPageAccordingToState()
        {
            m_ButtonFormPages[0] = (IButtonFormPage) new Page_AddEdit();
            m_ButtonFormPages[0].ParentWPFContainer = this;
            
            if (!frmButtonForm.Navigate((Page) m_ButtonFormPages[0]))
                 Log.Info(string.Format("{0}() - ButtonForm could not navigate to Page_AddEdit", MethodBase.GetCurrentMethod().Name));
        }

        /// <summary>
        /// When this window closes position the Hooked Window back to it's original position
        /// </summary>
        private void Window_Closed(object sender, EventArgs e)
        {
           // GUICommon.PositionWindowBackToWhereItWas(HookedWindow, true);
            BHInteracter.SetAsActiveWindow(HookedWindow);
        }
    }
}
