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 System.IO;

namespace Test_Merge
{
    public partial class Settings : Form
    {
        private string _grandPrixUrl = "";
        private string _grandPrixName = "";
        private int _grandPrixYear = 2000;
        private string _selectedConfigFile;
        private List<string> _driverList = new List<string>();

        private F1TVEmulator Emulator = null;
        private ConfigurationTool Config = null;

        private bool CreatingZone = false;
        private Point ZoneP1;
        private Point ZoneP2;

        private bool CreatingWindow = false;
        private Point WindowP1;
        private Point WindowP2;

        List<Rectangle> WindowsToAdd = new List<Rectangle>();

        public string GrandPrixUrl { get => _grandPrixUrl; private set => _grandPrixUrl = value; }
        public string GrandPrixName { get => _grandPrixName; private set => _grandPrixName = value; }
        public int GrandPrixYear { get => _grandPrixYear; private set => _grandPrixYear = value; }
        public List<string> DriverList { get => _driverList; private set => _driverList = value; }
        public string SelectedConfigFile { get => _selectedConfigFile;private set => _selectedConfigFile = value; }

        public Settings()
        {
            InitializeComponent();
            Load();
        }
        private void Load()
        {
            RefreshUI();
        }
        private void RefreshUI()
        {
            
            lsbDrivers.DataSource = null;
            lsbDrivers.DataSource = DriverList;

            if (Directory.Exists(ConfigurationTool.CONFIGS_FOLDER_NAME))
            {
                lsbPresets.DataSource = null;
                lsbPresets.DataSource = Directory.GetFiles(ConfigurationTool.CONFIGS_FOLDER_NAME);
            }
            if (CreatingZone)
            {
                if (ZoneP1 == new Point(-1, -1))
                {
                    lblZonePointsRemaning.Text = "2 points Remaining";
                }
                else
                {
                    lblZonePointsRemaning.Text = "1 point Remaining";
                }
            }
            else
            {
                lblZonePointsRemaning.Text = "";
            }

            if (CreatingWindow)
            {
                if (WindowP1 == new Point(-1, -1))
                {
                    lblWindowPointsRemaining.Text = "2 points Remaining";
                }
                else
                {
                    lblWindowPointsRemaining.Text = "1 point Remaining";
                }
                lblWindowPointsRemaining.Text = ConfigurationTool.NUMBER_OF_ZONES - WindowsToAdd.Count() + " Windows remaining";
            }
            else
            {
                lblWindowPointsRemaining.Text = "";
                lblWindowsRemaining.Text = "";
            }
            if (Config != null)
            {
                pbxMain.Image = Config.MainZone.Draw();
                if(Config.MainZone.Zones.Count > 0)
                    pbxDriverZone.Image = Config.MainZone.Zones[0].Draw();
            }
        }
        private void CreateNewZone(Point p1, Point p2)
        {
            Rectangle dimensions = CreateAbsoluteRectangle(p1, p2);
            Config = new ConfigurationTool((Bitmap)pbxMain.Image, dimensions);
            RefreshUI();
        }
        private void CreateWindows(List<Rectangle> dimensions)
        {
            if (Config != null)
            {
                Config.AddWindows(dimensions);
            }
        }
        private void tbxGpUrl_TextChanged(object sender, EventArgs e)
        {
            GrandPrixUrl = tbxGpUrl.Text;
        }

        private void tbxGpName_TextChanged(object sender, EventArgs e)
        {
            GrandPrixName = tbxGpName.Text;
        }

        private void tbxGpYear_TextChanged(object sender, EventArgs e)
        {
            int year;
            try
            {
                year = Convert.ToInt32(tbxGpYear.Text);
            }
            catch
            {
                year = 1545;
            }
            GrandPrixYear = year;
        }

        private void btnAddDriver_Click(object sender, EventArgs e)
        {
            string newDriver = tbxDriverName.Text;
            DriverList.Add(newDriver);
            tbxDriverName.Text = "";
            RefreshUI();
        }

        private void btnRemoveDriver_Click(object sender, EventArgs e)
        {
            if (lsbDrivers.SelectedIndex >= 0)
            {
                DriverList.RemoveAt(lsbDrivers.SelectedIndex);
            }
            RefreshUI();
        }
        private void SwitchZoneCreation()
        {
            if (CreatingZone)
            {
                CreatingZone = false;
                lblZonePointsRemaning.Text = "";
            }
            else
            {
                CreatingZone = true;

                if (Config != null)
                    Config.ResetMainZone();

                if (CreatingWindow)
                    SwitchWindowCreation();

                if (Emulator != null && Emulator.Ready)
                {
                    Config = null;
                    pbxMain.Image = Emulator.Screenshot();
                }

                ZoneP1 = new Point(-1, -1);
                ZoneP2 = new Point(-1, -1);

                lblZonePointsRemaning.Text = "2 Points left";
            }
            RefreshUI();
        }
        private void SwitchWindowCreation()
        {
            if (CreatingWindow)
            {
                CreatingWindow = false;
            }
            else
            {
                CreatingWindow = true;

                if (Config != null)
                    Config.ResetWindows();

                if (CreatingZone)
                    SwitchZoneCreation();

                WindowP1 = new Point(-1, -1);
                WindowP2 = new Point(-1, -1);

                WindowsToAdd = new List<Rectangle>();
            }
            RefreshUI();
        }
        private void btnCreatZone_Click(object sender, EventArgs e)
        {
            SwitchZoneCreation();
        }
        private void btnCreateWindow_Click(object sender, EventArgs e)
        {
            SwitchWindowCreation();
        }
        private void pbxMain_MouseClick(object sender, MouseEventArgs e)
        {
            if (CreatingZone && pbxMain.Image != null)
            {
                //Point coordinates = pbxMain.PointToClient(new Point(MousePosition.X, MousePosition.Y));
                Point coordinates = e.Location;
                float xOffset = (float)pbxMain.Image.Width / (float)pbxMain.Width;
                float yOffset = (float)pbxMain.Image.Height / (float)pbxMain.Height;
                Point newPoint = new Point(Convert.ToInt32((float)coordinates.X * xOffset), Convert.ToInt32((float)coordinates.Y * yOffset));

                //MessageBox.Show("Coordinates" + Environment.NewLine + "Old : " + coordinates.ToString() + Environment.NewLine + "New : " + newPoint.ToString());

                if (ZoneP1 == new Point(-1, -1))
                {
                    ZoneP1 = newPoint;
                }
                else
                {
                    ZoneP2 = newPoint;
                    CreateNewZone(ZoneP1, ZoneP2);
                    SwitchZoneCreation();
                }
                RefreshUI();
            }
        }
        private void pbxMain_Click(object sender, EventArgs e)
        {
            //Not the right one to use visibly
        }
        private void pbxDriverZone_MouseClick(object sender, MouseEventArgs e)
        {
            if (CreatingWindow && pbxDriverZone.Image != null)
            {
                Point coordinates = e.Location;

                float xOffset = (float)pbxDriverZone.Image.Width / (float)pbxDriverZone.Width;
                float yOffset = (float)pbxDriverZone.Image.Height / (float)pbxDriverZone.Height;

                Point newPoint = new Point(Convert.ToInt32((float)coordinates.X * xOffset), Convert.ToInt32((float)coordinates.Y * yOffset));

                if (WindowP1 == new Point(-1, -1))
                {
                    WindowP1 = newPoint;
                }
                else
                {
                    WindowP2 = newPoint;
                    WindowsToAdd.Add(CreateAbsoluteRectangle(WindowP1, WindowP2));

                    if (WindowsToAdd.Count < ConfigurationTool.NUMBER_OF_ZONES)
                    {
                        WindowP1 = new Point(-1, -1);
                        WindowP2 = new Point(-1, -1);
                    }
                    else
                    {
                        WindowP1 = new Point(WindowP1.X, 0);
                        WindowP2 = new Point(WindowP2.X, pbxDriverZone.Image.Height);
                        CreateWindows(WindowsToAdd);
                        SwitchWindowCreation();
                    }
                }
                RefreshUI();
            }
        }
        private void pbxDriverZone_Click(object sender, EventArgs e)
        {
            //Not the right one to use visibly
        }
        private Rectangle CreateAbsoluteRectangle(Point p1, Point p2)
        {
            Point newP1 = new Point();
            Point newP2 = new Point();

            if (p1.X < p2.X)
            {
                newP1.X = p1.X;
                newP2.X = p2.X;
            }
            else
            {
                newP1.X = p2.X;
                newP2.X = p1.X;
            }

            if (p1.Y < p2.Y)
            {
                newP1.Y = p1.Y;
                newP2.Y = p2.Y;
            }
            else
            {
                newP1.Y = p2.Y;
                newP2.Y = p1.Y;
            }
            return new Rectangle(newP1.X, newP1.Y, newP2.X - newP1.X, newP2.Y - newP1.Y);
        }

        private async void btnRefresh_Click(object sender, EventArgs e)
        {
            btnRefresh.Enabled = false;
            if (Emulator == null || Emulator.GrandPrixUrl != tbxGpUrl.Text)
            {
                Emulator = new F1TVEmulator(tbxGpUrl.Text);
            }

            if (!Emulator.Ready)
            {
                Task<int> start = Task.Run(() => Emulator.Start());
                int errorCode = await start;
                if (errorCode != 0)
                {
                    string message;
                    switch (errorCode)
                    {
                        case 101:
                            message = "Error " + errorCode + " Could not start the driver. It could be because an other instance is runnin make sure you closed them all before trying again";
                            break;
                        case 102:
                            message = "Error " + errorCode + " Could not navigate on the F1TV site. Make sure the correct URL has been given and that you logged from chrome. It can take a few minutes to update";
                            break;
                        case 103:
                            message = "Error " + errorCode + " The url is not a valid url";
                            break;
                        case 104:
                            message = "Error " + errorCode + " The url is not a valid url";
                            break;
                        case 105:
                            message = "Error " + errorCode + " There has been an error trying to emulate button presses. Please try again";
                            break;
                        case 106:
                            message = "Error " + errorCode + " There has been an error trying to emulate button presses. Please try again";
                            break;
                        default:
                            message = "Could not start the emulator Error " + errorCode;
                            break;
                    }
                    MessageBox.Show(message);
                }
                else
                {
                    pbxMain.Image = Emulator.Screenshot();
                }
            }
            else
            {
                pbxMain.Image = Emulator.Screenshot();
            }
            btnRefresh.Enabled = true;
        }

        private void Settings_FormClosing(object sender, FormClosingEventArgs e)
        {
            if (Emulator != null)
            {
                Emulator.Stop();
            }
        }

        private void btnResetDriver_Click(object sender, EventArgs e)
        {
            if (Emulator != null)
            {
                Emulator.ResetDriver();
            }
        }

        private void btnSavePreset_Click(object sender, EventArgs e)
        {
            string presetName = tbxPresetName.Text;
            if (Config != null)
            {
                Config.SaveToJson(DriverList,presetName);
            }
            RefreshUI();
        }

        private void lsbPresets_SelectedIndexChanged(object sender, EventArgs e)
        {
            //Nothing
        }

        private void btnLoadPreset_Click(object sender, EventArgs e)
        {
            if (lsbPresets.SelectedIndex >= 0 && pbxMain.Image != null)
            {
                try
                {
                    string fileName = lsbPresets.Items[lsbPresets.SelectedIndex].ToString();
                    Reader reader = new Reader(fileName, (Bitmap)pbxMain.Image,false);
                    //MainZones #0 is the big main zone containing driver zones
                    Config = new ConfigurationTool((Bitmap)pbxMain.Image, reader.MainZones[0].Bounds);
                    Config.MainZone = reader.MainZones[0];
                    DriverList = reader.Drivers;

                    SelectedConfigFile = fileName;
                }
                catch (Exception ex)
                {
                    MessageBox.Show("Could not load the settings error :" + ex);
                }
                RefreshUI();
            }
        }
    }
}
