using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Imaging;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Windows.Forms;

namespace Cosmos.CommonManager
{
    /// <summary>
    /// FormDisplayTricker
    /// </summary>
    public class FormDisplayTricker
    {
        private static FormEx layerForm = null;
        private static Timer timer = null;
        private static bool isReadConfig = false;
        private static bool isUseFormDisplayTricker = false;
        private static string FormDisplayTrickerName = "DisplayTrickerForm";

        /// <summary> SetLayer </summary>
        public static void SetLayer(Form topControl)
        {
            try
            {
                if (false == IsUseFormDisplayTricker())
                    return;

                FormEx form = GetLayerForm();
                Image img = ScreenCaptureOpacityForm.GetScreen();
                form.BackgroundImage = img;
                form.Location = new Point(0, form.Height * -1 - 1);
                form.Show();
                form.Refresh();
                form.Location = new Point(0, 0);
                timer.Interval = 50;
                timer.Start();
            }
            catch (Exception ex)
            {
                RemoveLayer();
            }
        }

        /// <summary> RemoveLayer </summary>
        public static void RemoveLayer()
        {
            if (false == IsUseFormDisplayTricker())
                return;

            if (timer != null)
                timer.Stop();
            Form form = GetLayerForm();
            if (form == null)
                return;
            form.Hide();
        }

        private static bool IsUseFormDisplayTricker()
        {
            if (isReadConfig)
                return isUseFormDisplayTricker;

            isReadConfig = true;
            try
            {
                if (System.Diagnostics.Process.GetCurrentProcess().ProcessName.EndsWith(".vshost", StringComparison.OrdinalIgnoreCase)) // 디버깅으로 실행되면 사용안함
                {
                    isUseFormDisplayTricker = false;
                }
                else
                {
                    //string iniFilaName = System.IO.Path.Combine(Application.StartupPath, ".\\Application.INI");
                    //System.Xml.XmlDocument xdoc = new System.Xml.XmlDocument();
                    //xdoc.Load(iniFilaName);
                    //var node = xdoc.DocumentElement.SelectSingleNode("performance/display_tricker");
                    //if (node != null)
                    //    isUseFormDisplayTricker = node.InnerText == "1";
                    isUseFormDisplayTricker = true;
                }
            }
            catch
            {
                isUseFormDisplayTricker = false;
            }
            return isUseFormDisplayTricker;
        }

        private static FormEx GetLayerForm()
        {
            if (layerForm == null || layerForm.IsDisposed)
            {
                layerForm = new FormEx();
                layerForm.FormBorderStyle = FormBorderStyle.None;
                layerForm.StartPosition = FormStartPosition.Manual;
                layerForm.Opacity = 0.9999999999;
                layerForm.Location = new Point(0, 0);
                layerForm.Size = new Size(1024, 768);
                layerForm.ShowInTaskbar = false;
                layerForm.TopMost = true;
                layerForm.Name = FormDisplayTrickerName;
                timer = new Timer();
                timer.Tick += timer_Tick;
                timer.Interval = 50;
            }
            return layerForm;
        }

        private static void timer_Tick(object sender, EventArgs e)
        {
            FormDisplayTricker.RemoveLayer();
        }

        /// <summary> FormEx </summary>
        public class FormEx : Form
        {
            /// <summary> FormEx </summary>
            public FormEx()
            {
                base.SetStyle(ControlStyles.OptimizedDoubleBuffer | ControlStyles.AllPaintingInWmPaint | ControlStyles.ResizeRedraw, true);
            }

            /// <summary> OnDeactivate </summary>
            protected override void OnDeactivate(EventArgs e)
            {
                //base.OnDeactivate(e);
                this.Activate();
            }

            /// <summary> OnLostFocus </summary>
            protected override void OnLostFocus(EventArgs e)
            {
                base.OnLostFocus(e);
            }

            /// <summary> OnPaint </summary>
            protected override void OnPaint(PaintEventArgs e)
            {
                base.OnPaint(e);
            }

            /// <summary> OnPaintBackground </summary>
            protected override void OnPaintBackground(PaintEventArgs e)
            {
                base.OnPaintBackground(e);
            }
        }

        /// <summary> ScreenCaptureOpacityForm </summary>
        public class ScreenCaptureOpacityForm
        {
            /// <summary> GetScreen </summary>
            public static Image GetScreen()
            {
                Size sz = Screen.PrimaryScreen.Bounds.Size;
                IntPtr hDesk = GetDesktopWindow();
                IntPtr hSrce = GetWindowDC(hDesk);
                IntPtr hDest = CreateCompatibleDC(hSrce);
                IntPtr hBmp = CreateCompatibleBitmap(hSrce, sz.Width, sz.Height);
                IntPtr hOldBmp = SelectObject(hDest, hBmp);
                bool b = BitBlt(hDest, 0, 0, sz.Width, sz.Height, hSrce, 0, 0, CopyPixelOperation.SourceCopy | CopyPixelOperation.CaptureBlt);
                Bitmap bmp = Bitmap.FromHbitmap(hBmp);
                SelectObject(hDest, hOldBmp);
                DeleteObject(hBmp);
                DeleteDC(hDest);
                ReleaseDC(hDesk, hSrce);
                return bmp;
            }

            // P/Invoke declarations
            [DllImport("gdi32.dll")]
            static extern bool BitBlt(IntPtr hdcDest, int xDest, int yDest, int
            wDest, int hDest, IntPtr hdcSource, int xSrc, int ySrc, CopyPixelOperation rop);
            [DllImport("user32.dll")]
            static extern bool ReleaseDC(IntPtr hWnd, IntPtr hDc);
            [DllImport("gdi32.dll")]
            static extern IntPtr DeleteDC(IntPtr hDc);
            [DllImport("gdi32.dll")]
            static extern IntPtr DeleteObject(IntPtr hDc);
            [DllImport("gdi32.dll")]
            static extern IntPtr CreateCompatibleBitmap(IntPtr hdc, int nWidth, int nHeight);
            [DllImport("gdi32.dll")]
            static extern IntPtr CreateCompatibleDC(IntPtr hdc);
            [DllImport("gdi32.dll")]
            static extern IntPtr SelectObject(IntPtr hdc, IntPtr bmp);
            /// <summary> GetDesktopWindow </summary>
            [DllImport("user32.dll")]
            public static extern IntPtr GetDesktopWindow();
            /// <summary> GetWindowDC </summary>
            [DllImport("user32.dll")]
            public static extern IntPtr GetWindowDC(IntPtr ptr);
        }
    }
}
