using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Drawing.Text;
using System.Linq;
using System.Net.Mail;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace GFATask
{
    [Browsable(false), ToolboxItem(false)]
    public partial class ucAdminDesigns : UserControl
    {
        private List<string> FontFamilies { get => FontFamily.Families.Select(f => f.Name).OrderBy(f => f).ToList(); }

        private ColorDialog ColorDialog { get; set; } = new ColorDialog() { AllowFullOpen = true, AnyColor = true, FullOpen = true };

        public List<TableControlChange> ControlChanges { get; } = new List<TableControlChange>();



        private void DoFontFamily(object value)
        {
            Config.Main.FontFamily = value.ToString();
            typeof(Forms).GetProperties().ToList().ForEach(prop =>
            {
                FormEx form = (FormEx)prop.GetValue(typeof(Forms));
                Font font = new Font((string)value, Config.User.Window.FontSize);
                form.Font = font;
                Accumulations.Controls(form).ToList().ForEach(ctl => ctl.Font = font);
            });
            Win32API.SendMessage(Forms.Main.Handle, (int)WM.ENTERSIZEMOVE, 0, 0);
            Win32API.SendMessage(Forms.Main.Handle, (int)WM.EXITSIZEMOVE, 0, 0);
        }


        private void DoWindowRadius(object value)
        {
            Config.Main.Sizes.Window.Radius = int.Parse(value.ToString());
        }


        private void DoListBorderX(object value)
        {
            Config.Main.Sizes.List.Border = new Point(int.Parse(value.ToString()), Config.Main.Sizes.List.Border.Y);
        }

        private void DoListBorderY(object value)
        {
            Config.Main.Sizes.List.Border = new Point(Config.Main.Sizes.List.Border.X, int.Parse(value.ToString()));
        }

        private void CreateGeneralBindings()
        {
            cbFontFamily.DrawItem += LbFontFamily_DrawItem;
            cbFontFamily.Items.AddRange(FontFamilies.ToArray());

            cbFontFamily.SelectedItem = Config.Main.FontFamily;
            cbFontFamily.SelectedIndexChanged += (sender, e) => { if (this.Created) XObjects.PreChanging.Add(Config.Main, "FontFamily", (sender as ComboBox), (sender as ComboBox).SelectedItem, this.DoFontFamily); };
        }

        private void LbFontFamily_DrawItem(object sender, DrawItemEventArgs e)
        {
            string fontfamilyitem = (string)(sender as ListBox).Items[e.Index];
            e.DrawBackground();
            e.DrawFocusRectangle();
            e.Graphics.DrawString(fontfamilyitem, new Font(fontfamilyitem, Config.User.Window.FontSize), new SolidBrush((sender as ListBox).ForeColor), e.Bounds);
        }


        /// <summary>
        /// Fügt der "Zurücksetzen"-Auflistung das Steuerelement hinzu, damit der alte Wert wiederhergestellt werden kann
        /// </summary>
        /// <param name="control"></param>
        private void AddResetButton(Control control)
        {
            if (!this.ControlChanges.Select(change => change.Control).Contains(control))
            {
                TableControlChange change = new TableControlChange(tableDesign, control.Location, 25);
                change.Click += (sender, e) =>
                {
                    XObjects.PreChanging.Reset(change.Control);
                    (sender as TableControlChange).Clear();
                    this.ControlChanges.Remove(change);
                    tableDesign.Invalidate();
                };
                this.ControlChanges.Add(change);
            }
        }


        private void CreateSizeBindings()
        {
            numWindowRadius.Value = (decimal)Config.Main.Sizes.Window.Radius;
            numWindowRadius.ValueChanged += (sender, e) => { if (this.Created) XObjects.PreChanging.Add(Config.Main.Sizes.Window, "Radius", (sender as NumericEx), (int)(sender as NumericEx).Value, this.DoWindowRadius); };

            numWindowBorder.Value = (decimal)Config.Main.Sizes.Window.Border;
            numWindowBorder.ValueChanged += (sender, e) => { if (this.Created) XObjects.PreChanging.Add(Config.Main.Sizes.Window, "Border", (sender as NumericEx), (int)(sender as NumericEx).Value, this.DoWindowBorder); };

            numAppListX.Value = (decimal)Config.Main.Sizes.List.Border.X;
            numAppListX.ValueChanged += (sender, e) => { if (this.Created) XObjects.PreChanging.Add(Config.Main.Sizes.List.Border, "X", (sender as NumericEx), (int)(sender as NumericEx).Value, this.DoListBorderX); };

            numAppListY.Value = (decimal)Config.Main.Sizes.List.Border.Y;
            numAppListY.ValueChanged += (sender, e) => { if (this.Created) XObjects.PreChanging.Add(Config.Main.Sizes.List.Border, "Y", (sender as NumericEx), (int)(sender as NumericEx).Value, this.DoListBorderY); };
        }


        public void DoWindowBackColor(object value)
        {
            Config.Main.Colors.Window.BackColor = (Color)value;
            this.SetNewDesign();
        }

        private void DoWindowBorderColor(object value)
        {
            Config.Main.Colors.Window.Border = (Color)value;
            this.SetNewDesign();
        }

        private void DoWindowAction(object value)
        {
            Config.Main.Colors.Window.Action = (Color)value;
            this.SetNewDesign();
        }

        private void DoWindowTitlebarBackColor(object value)
        {
            Config.Main.Colors.Window.TitlebarBackColor = (Color)value;
            this.SetNewDesign();
        }

        private void DoGroupAction(object value)
        {
            Config.Main.Colors.Window.Action = (Color)value;
            this.SetNewDesign();
        }
        private void DoGroupBorderColor(object value)
        {
            Config.Main.Colors.Window.Border = (Color)value;
            this.SetNewDesign();
        }
        private void DoGroupBackColor(object value)
        {
            Config.Main.Colors.Window.BackColor = (Color)value;
            this.SetNewDesign();
        }
        private void DoGroupTitlebarBackColor(object value)
        {
            Config.Main.Colors.Window.TitlebarBackColor = (Color)value;
            this.SetNewDesign();
        }

        private void DoListBorderColor(object value)
        {
            Config.Main.Colors.List.Border = (Color)value;
            this.SetNewDesign();
        }

        private void DoAppDefaultBackColor(object value)
        {
            Config.Main.Colors.Apps.Default.BackColor = (Color)value;
            this.SetNewDesign();
        }

        private void DoAppDefaultBorderColor(object value)
        {
            Config.Main.Colors.Apps.Default.Border = (Color)value;
            this.SetNewDesign();
        }

        private void DoAppDefaultForeColor(object value)
        {
            Config.Main.Colors.Apps.Default.ForeColor = (Color)value;
        }

        private void DoAppDefaultImage(object value)
        {
            Config.Main.Colors.Apps.Default.Image = (Color)value;
            this.SetNewDesign();
        }

        private void DoAppHoverBackColor(object value)
        {
            Config.Main.Colors.Apps.Hover.BackColor = (Color)value;
            this.SetNewDesign();
        }

        private void DoAppHoverBorderColor(object value)
        {
            Config.Main.Colors.Apps.Hover.Border = (Color)value;
            this.SetNewDesign();
        }

        private void DoAppHoverForeColor(object value)
        {
            Config.Main.Colors.Apps.Hover.ForeColor = (Color)value;
            this.SetNewDesign();
        }

        private void DoAppHoverImage(object value)
        {
            Config.Main.Colors.Apps.Hover.Image = (Color)value;
            this.SetNewDesign();
        }

        private void DoWindowBorder(object value)
        {
            Config.Main.Sizes.Window.Border = int.Parse(value.ToString());
            this.SetWindowBorder();
            this.SetNewDesign();
        }

        private void DoLoadingAnimationDot1(object value)
        {
            Config.Main.Colors.LoadingAnimation.Dot1 = (Color)value;
            XObjects.LoadingPanel.MovingPoints[0].Fill = Config.Main.Colors.LoadingAnimation.Dot1;
            this.SetNewDesign();
        }

        private void DoLoadingAnimationDot2(object value)
        {
            Config.Main.Colors.LoadingAnimation.Dot2 = (Color)value;
            XObjects.LoadingPanel.MovingPoints[1].Fill = Config.Main.Colors.LoadingAnimation.Dot2;
            this.SetNewDesign();
        }

        private void DoLoadingAnimationDot3(object value)
        {
            Config.Main.Colors.LoadingAnimation.Dot3 = (Color)value;
            XObjects.LoadingPanel.MovingPoints[2].Fill = Config.Main.Colors.LoadingAnimation.Dot3;
            this.SetNewDesign();
        }

        private void DoLoadingAnimationDot4(object value)
        {
            Config.Main.Colors.LoadingAnimation.Dot4 = (Color)value;
            XObjects.LoadingPanel.MovingPoints[3].Fill = Config.Main.Colors.LoadingAnimation.Dot4;
            this.SetNewDesign();
        }




        private void CreateColorBindings()
        {
            this.DesignComboBoxes(cbWindowBackColor, Config.Main.Colors.Window.BackColor);
            cbWindowBackColor.SelectedIndexChanged += (sender, e) => { if (this.Created) XObjects.PreChanging.Add(Config.Main.Colors.Window, "BackColor", (sender as ComboBox), ToColor((sender as ComboBox).SelectedItem.ToString()), this.DoWindowBackColor); };
            
            this.DesignComboBoxes(cbWindowBorderColor, Config.Main.Colors.Window.Border);
            cbWindowBorderColor.SelectedIndexChanged += (sender, e) => { if (this.Created) XObjects.PreChanging.Add(Config.Main.Colors.Window, "Border", (sender as ComboBox), ToColor((sender as ComboBox).SelectedItem.ToString()), this.DoWindowBorderColor); };

            this.DesignComboBoxes(cbWindowActionColor, Config.Main.Colors.Window.Action);
            cbWindowActionColor.SelectedIndexChanged += (sender, e) => { if (this.Created) XObjects.PreChanging.Add(Config.Main.Colors.Window, "Action", (sender as ComboBox), ToColor((sender as ComboBox).SelectedItem.ToString()), this.DoWindowAction); };

            this.DesignComboBoxes(cbWindowTitlebarColor, Config.Main.Colors.Window.TitlebarBackColor);
            cbWindowTitlebarColor.SelectedIndexChanged += (sender, e) => { if (this.Created) XObjects.PreChanging.Add(Config.Main.Colors.Window, "TitlebarBackColor", (sender as ComboBox), ToColor((sender as ComboBox).SelectedItem.ToString()), this.DoWindowTitlebarBackColor); };

            this.DesignComboBoxes(cbGroupActionColor, Config.Main.Colors.GroupWindow.Action);
            cbGroupActionColor.SelectedIndexChanged += (sender, e) => { if (this.Created) XObjects.PreChanging.Add(Config.Main.Colors.GroupWindow, "Action", (sender as ComboBox), ToColor((sender as ComboBox).SelectedItem.ToString()), this.DoGroupAction); };

            this.DesignComboBoxes(cbGroupBackColor, Config.Main.Colors.GroupWindow.BackColor);
            cbGroupBackColor.SelectedIndexChanged += (sender, e) => { if (this.Created) XObjects.PreChanging.Add(Config.Main.Colors.GroupWindow, "BackColor", (sender as ComboBox), ToColor((sender as ComboBox).SelectedItem.ToString()), this.DoGroupBackColor); };

            this.DesignComboBoxes(cbGroupBorderColor, Config.Main.Colors.GroupWindow.Border);
            cbGroupBorderColor.SelectedIndexChanged += (sender, e) => { if (this.Created) XObjects.PreChanging.Add(Config.Main.Colors.GroupWindow, "Border", (sender as ComboBox), ToColor((sender as ComboBox).SelectedItem.ToString()), this.DoGroupBorderColor); };

            this.DesignComboBoxes(cbGroupTitlebarColor, Config.Main.Colors.GroupWindow.TitlebarBackColor);
            cbGroupTitlebarColor.SelectedIndexChanged += (sender, e) => { if (this.Created) XObjects.PreChanging.Add(Config.Main.Colors.GroupWindow, "TitlebarBackColor", (sender as ComboBox), ToColor((sender as ComboBox).SelectedItem.ToString()), this.DoGroupTitlebarBackColor); };

            this.DesignComboBoxes(cbListBorderColor, Config.Main.Colors.List.Border);
            cbListBorderColor.SelectedIndexChanged += (sender, e) => { if (this.Created) XObjects.PreChanging.Add(Config.Main.Colors.List, "Border", (sender as ComboBox), ToColor((sender as ComboBox).SelectedItem.ToString()), this.DoListBorderColor); };

                this.DesignComboBoxes(cbAppDefaultBackColor, Config.Main.Colors.Apps.Default.BackColor);
            cbAppDefaultBackColor.SelectedIndexChanged += (sender, e) => { if (this.Created) XObjects.PreChanging.Add(Config.Main.Colors.Apps.Default, "BackColor", (sender as ComboBox), ToColor((sender as ComboBox).SelectedItem.ToString()), this.DoAppDefaultBackColor); };

            this.DesignComboBoxes(cbAppDefaultForeColor, Config.Main.Colors.Apps.Default.ForeColor);
            cbAppDefaultForeColor.SelectedIndexChanged += (sender, e) => { if (this.Created) XObjects.PreChanging.Add(Config.Main.Colors.Apps.Default, "ForeColor", (sender as ComboBox), ToColor((sender as ComboBox).SelectedItem.ToString()), this.DoAppDefaultForeColor); };

            this.DesignComboBoxes(cbAppDefaultBorder, Config.Main.Colors.Apps.Default.Border);
            cbAppDefaultBorder.SelectedIndexChanged += (sender, e) => { if (this.Created) XObjects.PreChanging.Add(Config.Main.Colors.Apps.Default, "Border", (sender as ComboBox), ToColor((sender as ComboBox).SelectedItem.ToString()), this.DoAppDefaultBorderColor); };

            this.DesignComboBoxes(cbAppDefaultImage, Config.Main.Colors.Apps.Default.Image);
            cbAppDefaultImage.SelectedIndexChanged += (sender, e) => { if (this.Created) XObjects.PreChanging.Add(Config.Main.Colors.Apps.Default, "Image", (sender as ComboBox), ToColor((sender as ComboBox).SelectedItem.ToString()), this.DoAppDefaultImage); };

            this.DesignComboBoxes(cbAppHoverBackColor, Config.Main.Colors.Apps.Hover.BackColor);
            cbAppHoverBackColor.SelectedIndexChanged += (sender, e) => { if (this.Created) XObjects.PreChanging.Add(Config.Main.Colors.Apps.Hover, "BackColor", (sender as ComboBox), ToColor((sender as ComboBox).SelectedItem.ToString()), this.DoAppHoverBackColor); };

            this.DesignComboBoxes(cbAppHoverForeColor, Config.Main.Colors.Apps.Hover.ForeColor);
            cbAppHoverForeColor.SelectedIndexChanged += (sender, e) => { if (this.Created) XObjects.PreChanging.Add(Config.Main.Colors.Apps.Hover, "ForeColor", (sender as ComboBox), ToColor((sender as ComboBox).SelectedItem.ToString()), this.DoAppHoverForeColor); };

            this.DesignComboBoxes(cbAppHoverBorder, Config.Main.Colors.Apps.Hover.Border);
            cbAppHoverBorder.SelectedIndexChanged += (sender, e) => { if (this.Created) XObjects.PreChanging.Add(Config.Main.Colors.Apps.Hover, "Border", (sender as ComboBox), ToColor((sender as ComboBox).SelectedItem.ToString()), this.DoAppHoverBorderColor); };

            this.DesignComboBoxes(cbAppHoverImage, Config.Main.Colors.Apps.Hover.Image);
            cbAppHoverImage.SelectedIndexChanged += (sender, e) => { if (this.Created) XObjects.PreChanging.Add(Config.Main.Colors.Apps.Hover, "Image", (sender as ComboBox), ToColor((sender as ComboBox).SelectedItem.ToString()), this.DoAppHoverImage); };

            this.DesignComboBoxes(cbLoadingDot1, Config.Main.Colors.LoadingAnimation.Dot1);
            cbLoadingDot1.SelectedIndexChanged += (sender, e) => { if (this.Created) XObjects.PreChanging.Add(Config.Main.Colors.LoadingAnimation, "Dot1", (sender as ComboBox), ToColor((sender as ComboBox).SelectedItem.ToString()), this.DoLoadingAnimationDot1); };

            this.DesignComboBoxes(cbLoadingDot2, Config.Main.Colors.LoadingAnimation.Dot2);
            cbLoadingDot2.SelectedIndexChanged += (sender, e) => { if (this.Created) XObjects.PreChanging.Add(Config.Main.Colors.LoadingAnimation, "Dot2", (sender as ComboBox), ToColor((sender as ComboBox).SelectedItem.ToString()), this.DoLoadingAnimationDot2); };

            this.DesignComboBoxes(cbLoadingDot3, Config.Main.Colors.LoadingAnimation.Dot3);
            cbLoadingDot3.SelectedIndexChanged += (sender, e) => { if (this.Created) XObjects.PreChanging.Add(Config.Main.Colors.LoadingAnimation, "Dot3", (sender as ComboBox), ToColor((sender as ComboBox).SelectedItem.ToString()), this.DoLoadingAnimationDot3); };

            this.DesignComboBoxes(cbLoadingDot4, Config.Main.Colors.LoadingAnimation.Dot4);
            cbLoadingDot4.SelectedIndexChanged += (sender, e) => { if (this.Created) XObjects.PreChanging.Add(Config.Main.Colors.LoadingAnimation, "Dot4", (sender as ComboBox), ToColor((sender as ComboBox).SelectedItem.ToString()), this.DoLoadingAnimationDot4); };
        }


        private Color ToColor(string comboboxitem)
        {
            int[] rgb = new int[] { int.Parse(comboboxitem.Split(';')[0]), int.Parse(comboboxitem.Split(';')[1]), int.Parse(comboboxitem.Split(';')[2]) };
            return Color.FromArgb(rgb[0], rgb[1], rgb[2]);
        }

        private void DesignComboBoxes(ComboBox cb, Color color)
        {
            cb.BackColor = color;
            cb.ForeColor = Coloring.GetReadableForeColor(cb.BackColor);
            cb.Items.Add($"{color.R};{color.G};{color.B}");
            cb.SelectedIndex = 0;
            cb.MouseClick += cbColor_MouseClick;
            cb.SelectedIndexChanged += cbColor_SelectedIndexChanged;
        }

        private void cbColor_SelectedIndexChanged(object sender, EventArgs e)
        {
            ComboBox _this = sender as ComboBox;
            if (this.Created)
            {
                _this.BackColor = Color.FromArgb(int.Parse(_this.Text.Split(';')[0]), int.Parse(_this.Text.Split(';')[1]), int.Parse(_this.Text.Split(';')[2]));
                _this.ForeColor = Coloring.GetReadableForeColor(_this.BackColor);
            }
        }

        private void cbColor_MouseClick(object sender, MouseEventArgs e)
        {
            ComboBox _this = sender as ComboBox;
            ColorDialog.Color = _this.BackColor;
            if (ColorDialog.ShowDialog() == DialogResult.OK)
            {
                _this.BackColor = ColorDialog.Color;
                _this.ForeColor = Coloring.GetReadableForeColor(_this.BackColor);
                _this.Items.Add($"{ColorDialog.Color.R};{ColorDialog.Color.G};{ColorDialog.Color.B}");
                _this.SelectedIndex = _this.Items.Count- 1;
            }
        }


        public ucAdminDesigns()
        {
            InitializeComponent();

            this.SetDefaultDesign();

            this.CreateGeneralBindings();
            this.CreateSizeBindings();
            this.CreateColorBindings();


            XObjects.PreChanging.GetTemps(Accumulations.Controls(this));


            tableDesign.Controls.Cast<Control>().Where(ctl => ctl.GetType() != typeof(Label) && ctl.GetType() != typeof(AnimationButton)).ToList().ForEach(ctl =>
            {
                if (typeof(NumericEx) == ctl.GetType())
                {
                    (ctl as NumericEx).ValueChanged += (s, evt) =>
                    {
                        AddResetButton(ctl);
                    };
                }
                else if (typeof(ComboBox) == ctl.GetType())
                {
                    (ctl as ComboBox).SelectedIndexChanged += (s, evt) =>
                    {
                        AddResetButton(ctl);
                    };
                }
            });


            label11.Paint += Designer.DrawHeaderLabel;
            label4.Paint += Designer.DrawHeaderLabel;
            label18.Paint += Designer.DrawHeaderLabel;
        }


        private void numWindowRadius_ValueChanged(object sender, EventArgs e)
        {
            if(this.Created)
            {
                typeof(Forms).GetProperties().ToList().ForEach(prop =>
                {
                    FormEx form = ((FormEx)prop.GetValue(typeof(Forms)));

                    form.Radius = (int)numWindowRadius.Value;
                    if (form.Name == Forms.Main.Name)
                        ((FormMain)form).SetActionRegion();
                    form.Invalidate();
                });
            }
        }

        private void numWindowBorder_ValueChanged(object sender, EventArgs e)
        {
            if (this.Created)
            {
                this.SetWindowBorder();
            }
        }

        public void SetNewDesign()
        {
            JSON.Save(JSONConfig.Main);
            Config.Main = JSON.Read<Models.Config.Main>(Paths.MainConfig.FullName);

            XObjects.LoadingPanel.MovingPoints[0].Fill = Config.Main.Colors.LoadingAnimation.Dot1;
            XObjects.LoadingPanel.MovingPoints[1].Fill = Config.Main.Colors.LoadingAnimation.Dot2;
            XObjects.LoadingPanel.MovingPoints[2].Fill = Config.Main.Colors.LoadingAnimation.Dot3;
            XObjects.LoadingPanel.MovingPoints[3].Fill = Config.Main.Colors.LoadingAnimation.Dot4;

            typeof(Forms).GetProperties().ToList().ForEach(prop =>
            {
                FormEx form = ((FormEx)prop.GetValue(typeof(Forms)));
                form.SetDefaultDesign();
                form.Invalidate();
            });
        }

        public void SetWindowBorder()
        {
            typeof(Forms).GetProperties().ToList().ForEach(prop =>
            {
                FormEx form = ((FormEx)prop.GetValue(typeof(Forms)));

                form.BorderWidth = (int)numWindowBorder.Value;
                if (form.Name == Forms.Main.Name)
                {
                    ((FormMain)form).SetOpacityStep();
                    ((FormMain)form).SetStartValue();
                }
                form.Invalidate();
            });
        }


        /// <summary>
        /// Übernimmt alle vorläufigen Speicherungen in die JSON-Config
        /// </summary>
        /// <param name="json">Gibt die JSON-Config Datei an</param>
        private void SaveAll(JSONConfig json)
        {
            XObjects.PreChanging.CommitAll();
            this.ControlChanges.ForEach(change => change.Clear());
            this.ControlChanges.Clear();
            JSON.Save(json);
        }


        /// <summary>
        /// Leert die vorläufigen Speicherungen aus der Auflistung
        /// </summary>
        private void ResetAll()
        {
            XObjects.PreChanging.ResetAll();
            this.ControlChanges.ForEach(change => change.Clear());
            this.ControlChanges.Clear();
            tableDesign.Invalidate();
        }

        private void abtnAnwenden_Click(object sender, EventArgs e)
        {
            this.SaveAll(JSONConfig.Main);
            this.ResetAll();
            XObjects.FrontEndRefresh.Update(new GFATaskStream() { PipeType = NetPipeType.MainConfig });
        }

        private void abtnVerwerfen_Click(object sender, EventArgs e)
        {
            this.ResetAll();
        }

        private void numAppListX_ValueChanged(object sender, EventArgs e)
        {
            XObjects.AllAppListPanels.ForEach(applist =>
            {
                applist.Border = new Point(int.Parse(numAppListX.Value.ToString()), applist.Border.Y);
                applist.Invalidate(true);
            });
        }

        private void numAppListY_ValueChanged(object sender, EventArgs e)
        {
            XObjects.AllAppListPanels.ForEach(applist =>
            {
                int bottom = applist.Padding.Bottom < int.Parse(numAppListY.Value.ToString()) ? int.Parse(numAppListY.Value.ToString()) : applist.Padding.Bottom;
                applist.Padding = new Padding(applist.Padding.Left, applist.Padding.Top, applist.Padding.Right, bottom);
                applist.Padding = new Padding(applist.Padding.Left, applist.Padding.Top, applist.Padding.Right, bottom);
                applist.Border = new Point(applist.Border.X, int.Parse(numAppListY.Value.ToString()));
                applist.Invalidate(true);
            }); 
        }
    }
}
