using Remontor.Setting;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Drawing;
using System.Linq;
using System.Net;
using System.Runtime.InteropServices;
using System.Runtime.Remoting.Contexts;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
using static System.Windows.Forms.VisualStyles.VisualStyleElement;

namespace Remontor.Connector
{
    internal class Connect
    {

        private const int SWP_NOOWNERZORDER = 0x200;
        private const int SWP_NOREDRAW = 0x8;
        private const int SWP_NOZORDER = 0x4;
        private const int SWP_SHOWWINDOW = 0x0040;
        private const int WS_EX_MDICHILD = 0x40;
        private const int SWP_FRAMECHANGED = 0x20;
        private const int SWP_NOACTIVATE = 0x10;
        private const int SWP_ASYNCWINDOWPOS = 0x4000;
        private const int SWP_NOMOVE = 0x2;
        private const int SWP_NOSIZE = 0x1;
        private const int GWL_STYLE = (-16);
        private const uint WS_VISIBLE = 0x10000000;
        private const int WM_CLOSE = 0x10;
        private const uint WS_CHILD = 0x40000000;
        private const uint WS_POPUP = 0x80000000;
        private const uint WS_OVERLAPPED = 0x00000000;
        private const uint WS_THICKFRAME = 0x00040000;
        private const uint WS_DISABLED = 0x08000000;
        private const uint WS_MINIMIZE = 0x20000000;
        public const uint WS_MAXIMIZEBOX = 0x00010000;



        [DllImport("user32.dll")]
        static extern IntPtr SetParent(IntPtr hWndChild, IntPtr hWndNewParent);
        [DllImport("user32.dll")]
        static extern int SetWindowLong(IntPtr hWnd, int nIndex, uint dwNewLong);

        [DllImport("user32.dll", SetLastError = true)]
        private static extern IntPtr FindWindow(string lpClassName, string lpWindowName);

        [DllImport("user32.dll")]
        static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);

        [DllImport("user32.dll")]

        static extern bool MoveWindow(IntPtr Handle, int x, int y, int w, int h, bool repaint);
        public static IntPtr GetWindowHandleByTitle(string title)
        {
            return FindWindow(null, title);
        }



        private IModeMon ModeMonitor;
        private Process Proc;
        private bool Active = false;
        private IComp Comp;
        private string ConnectStr;
        public delegate void UpdateConnect();
        public event UpdateConnect Update;
        public Control View;
        public IntPtr hwnd;
        private bool RecconectFlag, RecconectFlagIp;


        public Connect(IComp comp) 
        {
            Comp = comp;
            ConnectStr = Comp.GetNetNameStr();

        }

        public Connect(IComp comp, IPAddress ip) 
        {
            this.Comp = comp;
            ConnectStr = ip.ToString();
        }

        public void ConnectSCCM(Control panel)
        {
            try {
                View = new Panel();
                View.Dock = DockStyle.Fill;
                panel.Controls.Add(View);
                ModeMonitor = new OneMon();
                Proc = Process.Start(SGlobalSetting.settingApp.pathApp, ConnectStr);
                //Proc = Process.Start(SGlobalSetting.settingApp.pathApp);
                
                Proc.EnableRaisingEvents = true;
                Proc.Exited += Proc_Exited;
                PauseStart(Proc, 5000);
                SetParent(Proc.MainWindowHandle, View.Handle);
                SetWindowLong(Proc.MainWindowHandle, GWL_STYLE, WS_VISIBLE);
                ModeMonitor.Resize(Proc, View);

                // hwnd = GetWindowHandleByTitle("Устанавливается контакт с агентом удаленного управления на клиенте " + ConnectStr);
                Thread.Sleep(50);
                hwnd = GetWindowHandleByTitle("Contacting Remote Control Agent on client " + ConnectStr);
                Point CenterView = new Point(View.Bounds.Width/2, View.Bounds.Height/2);
                Point CenterDraw = View.PointToScreen(CenterView);
                MoveWindow(hwnd, CenterDraw.X- 325, CenterDraw.Y - 125 ,650,250,true);
               
            }
            catch (Exception) {
                MessageBox.Show("Не верно заданно приложение для подключения.");
                ModeMonitor = new OffMon();
                SConnector.Panel.Controls.Remove(View);
                return;

            }
            
        }

        private void PauseStart(Process proc, int timeOutMs)
        {
            int i = 0;
            while ((proc.MainWindowHandle.ToInt64() == 0) && (i < timeOutMs))
            {
                Thread.Sleep(1);
                i++;
            }
        }

        private void Proc_Exited(object sender, EventArgs e)
        {
            
            SConnector.FormMain.Invoke(new MethodInvoker(delegate
            {
                DelBar();
            }));

            if (RecconectFlag)
            {
                if (RecconectFlagIp)
                {
                    SConnector.FormMain.Invoke(new MethodInvoker(delegate
                    {
                        ReconnectBarIp();
                    }));
                }
                else
                {
                    SConnector.FormMain.Invoke(new MethodInvoker(delegate
                    {
                        ReconnectBar();
                    }));
                }
                
            }
            RecconectFlag = false;
            RecconectFlagIp = false;

            Proc.Dispose();
            Proc = null;
        }

        public void Activ(bool act)
        {
            this.Active = act;
            View.Visible = act;
            if (act) Resize();
            if (act)
            {
                ShowWindow(hwnd, 5);
                Point CenterView = new Point(View.Bounds.Width / 2, View.Bounds.Height / 2);
                Point CenterDraw = View.PointToScreen(CenterView);
                MoveWindow(hwnd, CenterDraw.X - 325, CenterDraw.Y - 125, 650, 250, true);
            }
            else
            {
                ShowWindow(hwnd, 0);
            }


            ModeMonitor.Resize(Proc, View);
            Update();
        }

        public bool ActiveOn
        {
            get { return this.Active; }
           
        }

        public void Resize()
        {
            ModeMonitor.Resize(Proc, View);
            Point CenterView = new Point(View.Bounds.Width / 2, View.Bounds.Height / 2);
            Point CenterDraw = View.PointToScreen(CenterView);
            MoveWindow(hwnd, CenterDraw.X - 325, CenterDraw.Y - 125, 650, 250, true);
        }

        public IModeMon GetModeMon()
        {
            return ModeMonitor;
        }

        public IModeMon SetModeMon(IModeMon Mode)
        {
            ModeMonitor = ModeMonitor.Change(Mode);
            ModeMonitor.Resize(Proc, View);
            return ModeMonitor;
        }

        public IComp GetComp
        {
            get { return Comp; }
        }
        public string toString()
        {
            if (Comp.GetName() == null)
            {
                return Comp.GetNetNameStr();
            }
            return Comp.GetName() + "(" + Comp.GetNetNameStr() + ")";
        }


        public async void DelBar()
        {
            SConnector.DeleteConnect(this); 
            ModeMonitor = new OffMon();
            SConnector.Panel.Controls.Remove(View);

        }

        public async void ReconnectBar()
        {
            SConnector.NewConnect(Comp);
        }

        public async void ReconnectBarIp()
        {
            SConnector.NewConnectIP(Comp);
        }

        public void Delete()
        {
            if (Proc != null)
            {
                Proc.CloseMainWindow();
            }
        }

        public void Reconnect()
        {
            RecconectFlag = true;
            RecconectFlagIp = false;
            if (Proc != null)
            {

                Proc.CloseMainWindow();
            }
        }

        public void ReconnectIP()
        {
            RecconectFlag = true;
            RecconectFlagIp = true;
            if (Proc != null)
            {

                Proc.CloseMainWindow();
            }
        }
    }
}
