using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
//using GameServer;
using System.Diagnostics;
using System.Runtime.InteropServices;

namespace SmartScreen
{

    public partial class frmSmartScreen : Form

    {
    enum eScreenSetting
    {
        preset = 1,
        custom = 2
    }

    enum eScreenOrientation
    {
        portrait = 1,
        landscape = 2
    }


        [DllImport("user32.dll")]
        private static extern IntPtr SetParent(IntPtr hWndChild, IntPtr hWndNewParent);

        [DllImport("user32.dll")]
        static extern bool MoveWindow(IntPtr handle, int x, int y, int w, int h, bool repaint);

        [DllImport("USER32.DLL")]
        public static extern bool SetForegroundWindow(IntPtr hWnd);
 

        public System.Threading.Thread AGKthread;
        public IntPtr agkHandle;

        public Process pAGK;

        public int testVar;


        //****************************
        // Control Panel variables
        //****************************

        eScreenSetting iScreenSetting;
        int iScreenWidth;
        int iScreenHeight;
        bool blnFullScreen;
        bool blnIscreenDirty;


        public frmSmartScreen()

        {
            InitializeComponent();

            //***************************************
            // AGK Window Setup
            //***************************************
            pAGK = Process.Start(Application.StartupPath + "\\AGKPanel.exe");
            if (pAGK == null) return;
            bool success = pAGK.WaitForInputIdle(10000);
            if (success == false)
            {
                MessageBox.Show("Failed to initialise GUI window");
            }

            SetParent(pAGK.MainWindowHandle, AGKpanel.Handle);
            agkHandle = pAGK.MainWindowHandle;

            //****************************************
            // Start the network comms
            //****************************************
            for (int n = 3; n > 0; n--)
            {
                if (AGKNet.networkRunning != true)
                {
                    try
                    {
                        stsLabel.Text = "Starting Comms...";
                        AGKNet.SetupNet();

                        stsLabel.Text = "AGK Network Started ";
                        // Let the AGKNet thread find this form for feedback
                        AGKNet.setParentForm(this);
                        break;
                    }
                    catch
                    {
                    }


                }
                else
                {
                    AGKNet.Close();
                    stsLabel.Text = "Create";
                    break;
                }

            }  //end for - create/close network



        }


        private void frmSmartScreen_Load(object sender, EventArgs e)
        {

            // !! Set this to the current form. It allows AGKNet to write to your visible log window.
            // In AGKNet, you must set the parent parameter to be of the type of this form. (Press F12 on "parent" below)
            Log.parent = this;

            //  Initialise screen dimensions
            iScreenSetting = eScreenSetting.preset;
            rdoScreenPreset.Checked = true;
            cmbScreenSize.SelectedIndex = 0;
            cmbOrientation.SelectedIndex = 1;
            setScreenParameters(true);
            btnScreenSet.BackColor = Color.Transparent;

            //Create Tree Structure. This is created from the eNum Entity.eEntityType
            String[] arrEntity = Enum.GetNames(typeof(Entity.eEntityType));
            for (int n = 0; n < arrEntity.Length; n++) {
                treeEntities.Nodes.Add((string)arrEntity[n]);
            }

            //Set Screen
            setScreenParameters(true);
            setScreen();

        }

        /*
         * Method to allow other threads to write to screen log
         * Replace rtbLog with control and methods of your choice
         * Achieved by calling itself as a new action if invoked from another thread
         * By creating an action, it gets queued which makes it "safe".
         */

        private void frmSmartScreen_FormClosing(object sender, FormClosingEventArgs e)
        {

            try
            {
                AGKNet.Client[0].SendMessage("END");
                System.Threading.Thread.Sleep(100);
            }
            catch
            {

            }

        }

        private void frmSmartScreen_ResizeEnd(object sender, EventArgs e)
        {
            setScreenParameters(true);
            setScreen();
        }


        // @BAX2

        //*************************************************************
        public void processMessage(AGKmessage msg)
        //*************************************************************
        // Process Messages from the AGK Client
        // The requests will come from the AGKNet thread as invokes
        //*************************************************************     
        {

            // *****************************************
            // *** LEVEL 1 TYPES
            // *****************************************
            switch (msg.Type1)
            {

                #region 1/GENERIC
                // *****************************************
                // *** LEVEL 1 : GENERIC
                // *****************************************
                case (int)PktMessageType1.GENERIC:

                    // *****************************************
                    // *** LEVEL 2 TYPES
                    // *****************************************
                    switch (msg.Type2)
                    {

                        #region 2/GENERIC
                        // *****************************************
                        // *** LEVEL 2 : GENERIC
                        // *****************************************
                        case (int)PktMessageType2.GENERIC:

                            // For test purposes, set label1.text
                            //label1.Invoke(new Action(() => label1.Text = msg.Msg));
                            MessageBox.Show(msg.Msg);
                            testVar = 1;
                            break;


                        #endregion 2/GENERIC


                        #region 2/UNRECOGNISED
                        default:
                        break;


                        #endregion 2/UNRECOGNISED

                    }
                    break;

                #endregion


                #region 1/INPUT
                // *****************************************
                // *** LEVEL 1: INPUT
                // *****************************************
                case (int)PktMessageType1.INPUT:

                    break;


                #endregion 1/INPUT


                #region 1/ERROR
                // *****************************************
                // *** LEVEL 1 : ERROR
                // *****************************************
                case (int)PktMessageType1.ERROR:

                    MessageBox.Show(msg.Msg);

                    break;

                #endregion 1/ERROR

                #region 1/UNRECOGNISED
                // *****************************************
                // *** LEVEL 1 : UNRECOGNISED
                // *****************************************
                default:
                    break;


                #endregion 1/UNRECOGNISED
            }


        }


#region CONTROL_PANEL

        //************************************************************************************
        //  CONTROL PANEL SPECIFICS
        //************************************************************************************


        //****************************************************
        // Screen Resizing
        //****************************************************


        private void rdoScreenPreset_CheckedChanged(object sender, EventArgs e)
        {
            setScreenParameters(true);
        }

        private void rdoScreenCustom_CheckedChanged(object sender, EventArgs e)
        {
            setScreenParameters(true);
        }


        private void btnScreenSet_Click(object sender, EventArgs e)
        {

            setScreenParameters(true);
            setScreen();

        }

        private void cmbScreenSize_SelectedIndexChanged(object sender, EventArgs e)
        {
            setScreenParameters(true);
        }

        private void cmbOrientation_SelectedIndexChanged(object sender, EventArgs e)
        {
            setScreenParameters(true);

        }


        // *** If changing from custom to preset or vice-versa, set all controls
        private void setScreenParameters(Boolean force)
        {
            if (rdoScreenPreset.Checked)
            {
                iScreenSetting = eScreenSetting.preset;
                btnScreenSet.BackColor = Color.Red;
                blnIscreenDirty = true;
                numScreenX.Enabled = false;
                numScreenY.Enabled = false;
                cmbScreenSize.Enabled = true;
                cmbOrientation.Enabled = true;
            }
            else
            {
                iScreenSetting = eScreenSetting.custom;
                btnScreenSet.BackColor = Color.Red;
                blnIscreenDirty = true;
                numScreenX.Enabled = true;
                numScreenY.Enabled = true;
                cmbScreenSize.Enabled = false;
                cmbOrientation.Enabled = false;
            }
        }

        // ***********************************************
        // *** Set the screen up physically, and tell AGK
        // ***********************************************
        private void setScreen()
        {

            int dimX = 0;
            int dimY = 0;

            if (blnIscreenDirty == true) {
                blnIscreenDirty = false;
                btnScreenSet.BackColor = Color.Transparent;

                // Get the screen dimensions. 
                switch (iScreenSetting) {

                    case eScreenSetting.preset:

                    string[] sDims = cmbScreenSize.SelectedItem.ToString().Split(new char[] {'x'});

                    if (cmbOrientation.SelectedIndex == 1) 
                        {
                            dimX = int.Parse(sDims[0]);
                            dimY = int.Parse(sDims[1]);
                        } else {
                            dimX = int.Parse(sDims[1]);
                            dimY = int.Parse(sDims[0]);
                        }
                        break;

                    case eScreenSetting.custom:

                        dimX = (int)numScreenX.Value;
                        dimY = (int)numScreenY.Value;
                       break;

                }

                //Now convert screen dimensions to an appropriate panel size
                //if calc 1 > calc 2, then x dimension is constrained
                Single calc1 = (Single)dimX / dimY;
                Single calc2 = (Single)splitForm.Panel2.Width / splitForm.Panel2.Height;
                if (calc1 > calc2)
                {
                    AGKpanel.Width = splitForm.Panel2.Width - 30;
                    AGKpanel.Height = (int)((Single)splitForm.Panel2.Width / dimX * dimY) ;
                }
                else
                {
                    AGKpanel.Height = splitForm.Panel2.Height - 40;
                    AGKpanel.Width = (int)((Single)splitForm.Panel2.Height / dimY * dimX);
                }

                AGKpanel.Left = (splitForm.Panel2.Width / 2) - (AGKpanel.Width / 2);
                AGKpanel.Top = (splitForm.Panel2.Height / 2) - (AGKpanel.Height / 2);

                MoveWindow(agkHandle, 0, 0, AGKpanel.Width, AGKpanel.Height, false);
                SetForegroundWindow(agkHandle);
                if (AGKNet.Client[0] != null) { 
                    AGKNet.Client[0].SendMessage("RESIZE~" + AGKpanel.Width + "~" + AGKpanel.Height);
                    AGKNet.Client[0].SendMessage("TESTResized");
                }

            }
        }

        //***************************************************
        //  *** If anything in dimension box changes, run this
        //***************************************************


#endregion CONTROL_PANEL

        private void numScreenX_ValueChanged(object sender, EventArgs e)
        {
            setScreenParameters(true);
        }

        private void numScreenY_ValueChanged(object sender, EventArgs e)
        {
            setScreenParameters(true);

        }

        private void chkFullScreen_CheckedChanged(object sender, EventArgs e)
        {
            setScreenParameters(true);

        }


        private void splitForm_Panel2_Resize(object sender, EventArgs e)
        {
            setScreenParameters(true);
            setScreen();
        }

        private void AGKpanel_MouseEnter(object sender, EventArgs e)
        {
            AGKpanel.Focus();
        }

        private void btnNewSprite_Click(object sender, EventArgs e)
        {

            AGKNet.Client[0].SendMessage("100~100", PktMessageType1.SPRITE, PktMessageType2.CREATE);

        }



    }


}




