using System;
using System.ComponentModel;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Threading;
using System.Windows.Forms;

namespace GFATask
{
    [Browsable(false), ToolboxItem(false)]
    public partial class AppButton : AppListButton
    {
        private ContextMenuStrip _contextmenustrip = new ContextMenuStrip();
        public override ContextMenuStrip ContextMenuStrip
        {
            get
            {
                XObjects.ContextMenuStrip = _contextmenustrip;
                return _contextmenustrip;
            }
            set
            {
                _contextmenustrip = value;
                _contextmenustrip.Items.Clear();

                if (AppType == AppType.Favorites || XObjects.IsAdmin.Result)
                {
                    _contextmenustrip.Items.Add("Bearbeiten", null, (s, evt) =>
                    {
                        Forms.AppCreator.GetEditableItem(AppType, Accessor.GetAppList(AppType).Apps.Find(app => app.ID == this.ID));
                        Accessor.OpenForm("AppCreator", Forms.Main);
                    });

                    _contextmenustrip.Items.Add(new ToolStripSeparator());
                }

                _contextmenustrip.Items.Add("Zulässige Berechtigungen", null, (s, evt) =>
                {
                    XObjects.MessageBox(!Config.Main.UseActiveDirectoryGroups ? "Die Active Directory Berechtigungsfunktion für den GFATask ist nicht aktiviert.\nIhnen werden alle Apps angezeigt." : $"Diese App benötigt mindestens eine Mitgliedschaft in eine der aufgelisteten Gruppen:\n\n{(ActiveDirectoryGroups == null || ActiveDirectoryGroups.Length == 0 ? "Keine" : string.Join("\n", ActiveDirectoryGroups))}", NotifyButtons.OK, NotifyType.Message, new Size(280, !Config.Main.UseActiveDirectoryGroups ? 140 : 240), "Zulässige App-Berechtigungen", null);
                });
                _contextmenustrip.Items.Add("Wie oft wurde ich geklickt?", null, (s, evt) =>
                {
                    XObjects.MessageBox($"Diese App wurde {Prevalence.CountClicks}x von Ihnen ausgeführt.", NotifyButtons.OK, NotifyType.Message, new Size(250, 150), "Wie oft wurde ich geklickt?", null);
                });
                if (AppType == AppType.Favorites || XObjects.IsAdmin.Result)
                {
                    _contextmenustrip.Items.Add(new ToolStripSeparator());
                    _contextmenustrip.Items.Add(new ToolStripMenuItem($"{this.Text} entfernen", null, (s, evt) =>
                    {
                        if (AppType != AppType.Favorites)
                        {
                            if (XObjects.MessageBox($"Soll {this.Text} entfernt werden", NotifyButtons.YesNo, NotifyType.Message, new Size(300, 120), $"{this.Text} entfernen").Result == DialogResult.Yes)
                                Creator.RemoveApp(AppType, Accessor.GetAppList(AppType).Apps.Find(app => app.ID == this.ID));
                        }
                        else
                        {
                            Creator.RemoveApp(AppType, Accessor.GetAppList(AppType).Apps.Find(app => app.ID == this.ID));
                        }
                    })
                    { Name = "remove_applistbutton" });
                }
                else
                {
                    _contextmenustrip.Items.Add(new ToolStripSeparator());
                    _contextmenustrip.Items.Add(new ToolStripMenuItem($"{this.Text} zu Favoriten hinzufügen", null, (s, evt) =>
                    {
                        Models.App appnew = new Models.App()
                        {
                            ActiveDirectoryGroups = this.ActiveDirectoryGroups,
                            Group = this.GroupName,
                            ID = AppLists.Favorites.Apps == null || AppLists.Favorites.Apps.Count == 0 ? 1 : AppLists.Favorites.Apps.Max(app => app.ID) + 1,
                            Icon = Accessor.GetAppList(AppType).Apps.Find(app => app.ID == this.ID).Icon,
                            Name = this.Text,
                            Execute = this.Execute
                        };
                        File.Copy($@"{Paths.Icons.Directory}\{appnew.Icon}", Paths.Favorites.Icons.Directory + @"\" + appnew.Icon, true);
                        Creator.AddApp(AppType.Favorites, appnew);
                    })
                    { Name = "to_favorites" });
                }
            }
        }

        private string _description = "";
        public string Description
        {
            get => _description; set
            {
                _description = value;
                this.GetToolTipText();
            }
        }

        public override AppType AppType
        {
            get => base.AppType;
            set
            {
                base.AppType = value;
                this.ContextMenuStrip = _contextmenustrip;
            }
        }

        private DateTime _lastmodified = default(DateTime);
        public DateTime LastModified { get => _lastmodified; set => _lastmodified = value; }

        private DateTime _creationtime = default(DateTime);
        public DateTime CreationTime { get => _creationtime; set => _creationtime = value; }


        private string _groupname = "";
        /// <summary>
        /// Sollte die App einer Gruppe zugeordnet sein, wird der Name hier angezeigt
        /// </summary>
        [
            Description("Sollte die App einer Gruppe zugeordnet sein, wird der Name hier angezeigt"),
            DefaultValue(0)
        ]
        public string GroupName
        {
            get => _groupname;
            set => _groupname = value;
        }


        private Models.Execute[] _execute = new Models.Execute[0];
        /// <summary>
        /// Beinhaltet die ausführbaren Befehle für diese App
        /// </summary>
        public Models.Execute[] Execute
        {
            get => _execute;
            set
            {
                _execute = value;

                if (_execute.Any(exec =>
                        (exec.Command != null && (exec.Command.StartsWith("http") || exec.Command.StartsWith("www.") || exec.Command.StartsWith("intranet."))) ||
                        (exec.Args != null && (exec.Args.StartsWith("http") || exec.Args.StartsWith("www.") || exec.Args.StartsWith("intranet."))) ||
                        (XObjects.IsAppLnk(exec.Command) && Accessor.GetAppList(Cast.ToAppLink(exec.Command).AppType).Apps.Find(app => app.ID == Cast.ToAppLink(exec.Command).ID).Execute.Any(lnk => lnk.Command.StartsWith("http") || lnk.Command.StartsWith("www.") || lnk.Command.StartsWith("intranet.")))))
                {

                    string browsername = String.Empty;

                    if (XObjects.IsAppLnk(_execute[0].Command))
                    {
                        var applnk = Accessor.GetAppList(Cast.ToAppLink(_execute[0].Command).AppType).Apps.Find(app => app.ID == Cast.ToAppLink(_execute[0].Command).ID);
                        browsername = applnk.Execute[0].Command.StartsWith("http") || applnk.Execute[0].Command.StartsWith("www.") || applnk.Execute[0].Command.StartsWith("internet.") ? "default" : AlternateWebbrowser.GetName(applnk.Execute[0].Command);
                    }
                    else
                    {
                        browsername = (_execute[0].Command.StartsWith("http") || _execute[0].Command.StartsWith("www.") || _execute[0].Command.StartsWith("intranet.")) ? "default" : AlternateWebbrowser.GetName(_execute[0].Command);
                    }
                    AlternateWebbrowser.DrawWebBrowserIcon(this.Image, browsername, this.Text);
                    this.Invalidate();
                }

                if (AppType == AppType.Favorites)
                {

                    if (_execute.Any(exec =>
                        (exec.Command != null && (exec.Command.StartsWith("http") || exec.Command.StartsWith("www.") || exec.Command.StartsWith("intranet."))) ||
                        (exec.Args != null && (exec.Args.StartsWith("http") || exec.Args.StartsWith("www.") || exec.Args.StartsWith("intranet.")))) && XObjects.WebBrowsers.Count > 0)
                    {
                        _contextmenustrip.Items.Insert(1, new ToolStripMenuItem("Öffnen mit", XObjects.WebBrowsers.Select(browser => AlternateWebbrowser.GetImage(browser.Name)).ToArray().Merge(_contextmenustrip.ImageScalingSize, 2), XObjects.WebBrowsers.Where(browser => browser.Path != "unknown").Select(browser =>
                        {
                            var browsericon = AlternateWebbrowser.GetImage(browser.Name);
                            return new ToolStripMenuItem(browser.Name, browsericon, (s, evt) =>
                            {
                                var app = Accessor.GetAppList(AppType.Favorites).Apps.Find(listapp => listapp.ID == this.ID);

                                _execute.ToList().ForEach(exec =>
                                {
                                    if (exec.Args == null || exec.Args == "")
                                    {
                                        string website = exec.Command;
                                        exec.Args = website;
                                    }
                                    exec.Command = AlternateWebbrowser.GetExec(browser.Name);
                                    _description = $"Öffnet die verlinkte Internetadresse {this.Text} mit dem {browser.Name} Browser";
                                    this.Image = Image.FromFile(Cast.IconPath(AppType.Favorites, app.Icon));
                                    AlternateWebbrowser.DrawWebBrowserIcon(this.Image, browser.Name);
                                    this.Invalidate();
                                    this.OnMouseClick(new MouseEventArgs(MouseButtons.Left, 0, 0, 0, 0));
                                });
                                app.Execute = _execute;
                                app.Description = _description;
                                JSON.Save(JSONApp.Favorites);
                            });
                        }).ToArray()));
                        //_contextmenustrip.Items.Insert(1, new ToolStripMenuItem("Öffnen mit", AlternateWebbrowser.Installed.Select(browser => AlternateWebbrowser.GetImage(browser.Key)).ToArray().Merge(_contextmenustrip.ImageScalingSize, 2), AlternateWebbrowser.Installed.Select(browser =>
                        //  {
                        //      var browsericon = AlternateWebbrowser.GetImage(browser.Key);
                        //      return new ToolStripMenuItem(browser.Key, browsericon, (s, evt) =>
                        //     {
                        //              var app = Accessor.GetAppList(AppType.Favorites).Apps.Find(listapp => listapp.ID == this.ID);

                        //              _execute.ToList().ForEach(exec =>
                        //              {
                        //                  if (exec.Args == null || exec.Args == "")
                        //                  {
                        //                      string website = exec.Command;
                        //                      exec.Args = website;
                        //                  }
                        //                  exec.Command = AlternateWebbrowser.GetExec(browser.Key);
                        //                  _description = $"Öffnet die verlinkte Internetadresse {this.Text} mit dem {browser.Key} Browser";
                        //                  this.Image = Image.FromFile(Cast.IconPath(AppType.Favorites, app.Icon));
                        //                  AlternateWebbrowser.DrawWebBrowserIcon(this.Image, browser.Key);
                        //                  this.Invalidate();
                        //                  this.OnMouseClick(new MouseEventArgs(MouseButtons.Left, 0, 0, 0, 0));
                        //              });
                        //              app.Execute = _execute;
                        //              app.Description = _description;
                        //              JSON.Save(JSONApp.Favorites);
                        //          });
                        //  }).ToArray()));
                        _contextmenustrip.SetDefaultDesign();
                    }
                }
            }
        }


        private int _id = 0;
        /// <summary>
        /// Die eindeutige Identifikationsnummer des AppButtons
        /// </summary>
        [
            Description("Die eindeutige Identifikationsnummer des AppButtons"),
            DefaultValue(0)
        ]
        public int ID
        {
            get => _id;
            set => _id = value;
        }

        
        public AppButton()
        {
            InitializeComponent();
            this.TextAlign = ContentAlignment.MiddleLeft;
            ContextMenuStrip.SetDefaultDesign();
        }



        protected override void OnHandleCreated(EventArgs e)
        {
            base.OnHandleCreated(e);
            this.GetToolTipText();
        }

        protected override void OnResize(EventArgs e)
        {
            base.OnResize(e);
            this.Width = this.ImageOnly ? this.Height : this.ActualWidth;
        }

        protected override void OnMouseHover(EventArgs e)
        {
            base.OnMouseHover(e);
        }

        protected override void OnMouseLeave(EventArgs e)
        {
            base.OnMouseLeave(e);
        }


      
        protected override void OnTextChanged(EventArgs e)
        {
            base.OnTextChanged(e);

            if (AppType == AppType.Favorites || XObjects.IsAdmin.Result)
            {
                if (_contextmenustrip.Items["remove_applistbutton"] != null)
                {
                    _contextmenustrip.Items["remove_applistbutton"].Text = $"{this.Text} entfernen";
                    _contextmenustrip.Items["remove_applistbutton"].Click += (sender, evt) =>
                    {
                        if(AppType != AppType.Favorites)
                        {
                            if (XObjects.MessageBox($"Soll {this.Text} entfernt werden", NotifyButtons.YesNo, NotifyType.Message, new Size(300, 120), $"{this.Text} entfernen").Result == DialogResult.Yes)
                                Creator.RemoveApp(AppType, Accessor.GetAppList(AppType).Apps.Find(app => app.ID == this.ID));
                        }
                        else
                        {
                            Creator.RemoveApp(AppType, Accessor.GetAppList(AppType).Apps.Find(app => app.ID == this.ID));
                        }
                    };
                }
            }
        }


        protected override void OnMouseClick(MouseEventArgs e)
        {
            base.OnMouseClick(e);
            if (e.Button == MouseButtons.Left)
            {
                if (this.ClientRectangle.Contains(e.Location))
                {
                    if(AppType == AppType.Admin || AppType == AppType.User || AppType == AppType.Menu)
                    {
                        Accessor.SetAppCounter(AppType, _id);
                    }
                    else if(AppType == AppType.Favorites)
                    {
                        if (XObjects.IsAppLnk(this.Execute[0].Command)) 
                        {
                            AppLnk lnk = Cast.ToAppLink(this.Execute[0].Command);
                            Models.App applnk = lnk.ToApp();
                            Accessor.SetAppCounter(lnk.AppType, lnk.ID);
                            if (applnk.LastModified > this.LastModified)
                            {
                                var applist = Accessor.GetAppList(this.AppType);
                                var app = applist.Apps[applist.Apps.FindIndex(appitem => appitem.ID == this.ID)];

                                if (!System.Drawing.Comparer.Image(Accessor.GetAppListPanel(lnk.AppType).SortedList.Find(button => button.Name == Cast.AppButtonName(lnk.AppType, applnk)).Image, this.Image))
                                {
                                    File.Copy(Cast.IconPath(lnk.AppType, applnk.Icon), Cast.IconPath(AppType.Favorites, app.Icon), true);
                                    using (FileStream fs = new FileStream(Cast.IconPath(AppType.Favorites, app.Icon), FileMode.Open, FileAccess.Read, FileShare.ReadWrite | FileShare.Delete))
                                    {
                                        this.Image = Image.FromStream(fs);
                                    }
                                }
                                app.LastModified = DateTime.Now;
                                this.LastModified = DateTime.Now;
                            }
                        }
                    }

                    Prevalence.CountUp();
                    this.GetToolTipText();
                    if (Config.User.Prevalence)
                    {
                        this.StepUpPrevalence(this.Parent.Controls.IndexOf(this) == 0 ? null : this.Parent.Controls[this.Parent.Controls.IndexOf(this) - 1]);
                    }
                    if (_execute != null && _execute.Length > 0)
                    {
                        new Thread(new ThreadStart(delegate
                        {
                            foreach (var exec in _execute)
                            {
                                if (AppExecution.FromApp(this.Text, exec.Command, exec.Args == null ? "" : string.Join(" ", exec.Args)))
                                {
                                    break;
                                }
                            }
                        }))
                        { IsBackground = true, Priority = ThreadPriority.BelowNormal }.Start();
                    }
                    if (Forms.AppButtonGroup.Visible)
                    {
                        Forms.AppButtonGroup.Close();
                    }
                }
            }
        }


        private void GetToolTipText()
        {
            this.ToolTipText = $"{this.Text}\n\n{(_description != "" ? _description : "")}";
            //this.ToolTipText = $"App: {this.Text}\n" +
            //      $"{(this.GroupName != null && this.GroupName != string.Empty ? $"Gruppe: {this.GroupName}\n" : "")}" +
            //      $"Geklickt: {this.Prevalence.CountClicks}x";
        }



        /// <summary>
        /// Setzt den Index des AppButtons solange herunter, bis dieser richtig eingegliedert wurde
        /// </summary>
        /// <param name="next">Der nächste AppButton, links von diesem</param>
        private void StepUpPrevalence(Control next)
        {
            if(this.Parent.Parent != null && this.Parent.Parent.GetType() == typeof(FormAppButtonGroup))
            {
                var virtual_form = ((FormAppButtonGroup)this.Parent.Parent);
                var virtual_applist = ((FlowLayoutPanel)this.Parent);
                virtual_form.MyGroupButton.Prevalence = virtual_applist.Controls.OfType<AppButton>().ToList().Find(
                    appbutton => appbutton.Prevalence.CountClicks == virtual_applist.Controls.OfType<AppButton>().ToList().Max(appbtn => appbtn.Prevalence.CountClicks)).Prevalence;
                var applistpanel = ((FlowContent)virtual_form.MyGroupButton.Parent);
                var groupbutton = virtual_form.MyGroupButton;
                var nextbutton = applistpanel.GetNextControl(virtual_form.MyGroupButton, false);

                if (nextbutton != null && groupbutton.Prevalence.CountClicks >= ((AppListButton)nextbutton).Prevalence.CountClicks)
                {
                    applistpanel.Controls.SetChildIndex(virtual_form.MyGroupButton, applistpanel.Controls.GetChildIndex(nextbutton));
                    this.StepUpPrevalence(next);
                }
            }
            if (next != null)
            {
                if ((next.GetType() == typeof(AppButton) && this.Prevalence.CountClicks >= ((AppButton)next).Prevalence.CountClicks) ||
                    (next.GetType() == typeof(GroupButton) && this.Prevalence.CountClicks >= ((GroupButton)next).Prevalence.CountClicks))
                {
                    if(this.Parent.GetType() == typeof(FormAppButtonGroup))
                    {
                        // Neue Anordnung in der Gruppenliste
                        ((FlowLayoutPanel)this.Parent).Controls.SetChildIndex(this, ((FlowLayoutPanel)this.Parent).Controls.GetChildIndex(next));
                        ((FlowContent)this.Parent.Parent).Controls.SetChildIndex(((FormAppButtonGroup)this.Parent).MyGroupButton, ((FlowContent)this.Parent.Parent).Controls.GetChildIndex(next));
                    }
                    else
                    {
                        // Neue Anordnung in der gesamten App-Liste
                        this.Parent.Controls.SetChildIndex(this, this.Parent.Controls.GetChildIndex(next));
                       this.StepUpPrevalence(this.Parent.Controls.IndexOf(this) == 0 ? null : this.Parent.Controls[this.Parent.Controls.IndexOf(this) - 1]);
                    }
                }
            }
        }
    }
}
