using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Windows.Forms.Layout;
using System.Xml;

namespace GFATask
{
    public partial class AppListPanel : Panel
    {
        /// <summary>
        /// Ist die Maus im heruntergedrückten Zustand
        /// </summary>
        private bool mousedown = false;

        /// <summary>
        /// Definiert den Bereich in dem der Name der Appliste angezeigt werden soll
        /// </summary>
        private Rectangle textbounds = Rectangle.Empty;

        /// <summary>
        /// Gibt den Bereich zum vergrößern der Appliste an
        /// </summary>
        private Rectangle gripbounds = Rectangle.Empty;

        /// <summary>
        /// Gibt die aktuelle Höhe aus. Sobald sich die Höhe der AppList ändert, wird diese hier aktualisiert
        /// </summary>
        private int tempheight = 0;


        private List<AppListButton> _sortedlist = new List<AppListButton>();
        /// <summary>
        /// Beinhaltet alle App-Steuerelemente nach der Ausführung der Methode "CreateButtons"
        /// </summary>
        [Browsable(false)]
        public List<AppListButton> SortedList
        {
            get => _sortedlist;
            private set => _sortedlist = value;
        }


        private bool _islast = false;
        /// <summary>
        /// Handelt es sich um die unterste Liste im GFA-Task, wird diese an in der Höhe die verbeleibende Fläche angepasst
        /// </summary>
        [Browsable(false)]
        public bool IsLast
        {
            get => _islast;
            set
            {
                _islast = value;
                _resizing = !value;
                if (_islast)
                {
                    this.Height = Forms.Main.Height - Forms.Main.Padding.Vertical - Forms.Main.ActionRegionHeight - XObjects.AllAppListPanels.Where(alp => alp.Showing && !alp.IsLast).Sum(alp => alp.Height);
                    this.SetMinmimumSize();
                }
                else
                {
                    this.Dock = DockStyle.Top;
                    if(!this.DesignMode)
                        this.Height = Accessor.GetListProperties(_apptype).Height;
                }
            }
        }


        private bool _showing = false;
        /// <summary>
        /// Definiert, ob das Panel sichtbar ist, oder nicht
        /// </summary>
        public bool Showing
        {
            get => _showing;
            set
            {
                _showing = value;
                this.Visible = _showing;
            }
        }
    

        private AppType _apptype = AppType.None;
        /// <summary>
        /// Definiert den Apptypen der in des AppListPanels
        /// </summary>
        [Description("Definiert den Apptypen der in des AppListPanels")]
        public AppType AppType
        {
            get => _apptype;
            set
            {
                _apptype = value;
                this.AllowDrop = _apptype == AppType.Favorites;
            }
        }


        private bool _grouping = false;
        /// <summary>
        /// Definiert, ob die AppButtons des Panels gruppiert werden, oder nicht
        /// </summary>
        public bool Grouping { 
            get => _grouping;
            set
            {
                _grouping = value;
                this.Invalidate();
            }
        }


        /// <summary>
        /// Ein angepasstes FlowLayoutPanel, welches in das AppListPanel integriert wurde
        /// </summary>
        [Browsable(false)]
        public FlowContent FlowContent
        {
            get => flowcontent;
        }


        private Color _bordercolor = SystemColors.ActiveBorder;
        /// <summary>
        /// Bestimmt die Rahmenfarbe des AppListPanels
        /// </summary>
        [
            Description("Bestimmt die Rahmenfarbe des AppListPanels"),
            DefaultValue(typeof(Color), "ActiveBorder")
        ]
        public Color BorderColor
        {
            get => _bordercolor;
            set
            {
                _bordercolor = value;
            }
        }


        private string _listname = "ListName";
        /// <summary>
        /// Bestimmt den Text, der auf der linken Seite, vertikal dargestellt werden soll
        /// </summary>
        [
            Description("Bestimmt den Text, der auf der linken Seite, vertikal dargestellt werden soll"),
            DefaultValue("ListName")
        ]
        public string ListName
        {
            get => _listname;
            set
            {
                _listname = value;
                textbounds = new Rectangle(new Point(0, 0), new Size((int)Math.Floor(TextRenderer.MeasureText(_listname, this.Font).Height * 1.5), this.Height));
                this.SetListNamePadding();
                this.SetMinmimumSize();
                this.Invalidate(textbounds);
            }
        }


        private Point _border = new Point(2, 2);
        /// <summary>
        /// Bestimmt die Breite der Trennungslinien in der Vertikalen und Horizontalen
        /// </summary>
        [
            Description("Bestimmt die Breite der Trennungslinien in der Vertikalen und Horizontalen"),
            DefaultValue(typeof(Size), "2,2")
        ]
        public Point Border
        {
            get => _border;
            set
            {
                _border = value;
                this.Invalidate();
            }
        }


        private bool _resizing = true;
        /// <summary>
        /// Bestimmt, ob sich das AppListPanel vergrößern lässt, oder nicht
        /// </summary>
        [
            Description("Bestimmt, ob sich das AppListPanel vergrößern lässt, oder nicht"),
            DefaultValue(true)
        ]
        public bool Resizing
        {
            get => _resizing;
            set
            {
                _resizing = value;
                this.Invalidate();
            }
        }


        public AppListPanel()
        {
            InitializeComponent();
            this.SetStyle(ControlStyles.UserPaint | ControlStyles.AllPaintingInWmPaint | ControlStyles.EnableNotifyMessage | ControlStyles.ResizeRedraw, true);
            tempheight = this.Height;
            this.SetListNamePadding();
            this.SetMinmimumSize();
            this.AutoSizeMode = AutoSizeMode.GrowAndShrink;
        }

        /// <summary>
        /// Liest dynamisch die vorhandenen Citrix-Anwendungen aus dem Startmenü aus. Diese werden nie in einer Liste gespeichert und sind immer nur zur Laufzeit verfügbar
        /// </summary>
        /// <param name="applist"></param>
        private void GetCitrixApps(Models.AppList<Models.App> applist)
        {
            applist.Apps = applist.Apps.Except(AppLists.Citrix.Apps.ToArray()).ToList();
            string icaselfservice = Paths.Citrix.ICASelfService.FullName;
            string ctxappslocalization = Paths.Citrix.Apps.Directory;
            XmlDocument xml = new XmlDocument();
            if(new DirectoryInfo(ctxappslocalization).GetFiles("*.xml", SearchOption.TopDirectoryOnly).Length != 0)
            {
                xml.Load(new DirectoryInfo(ctxappslocalization).GetFiles("*.xml", SearchOption.TopDirectoryOnly).First().OpenRead());
                xml.SelectNodes(Config.Main.Citrix.XMLNodes).Cast<XmlNode>().ToList().ForEach(node =>
                {
                    Func<string, string> value = name => node.SelectSingleNode(name).InnerText;
                    Models.App app = new Models.App() { ID = AppLists.Citrix.Apps.Count + 1, Execute = new Models.Execute[] { new Models.Execute() { Command = icaselfservice, Args = value("LaunchCommandLine") } }, Group = value("Category"), Name = value("FriendlyName") };

                    if(Directory.Exists(EnvironmentManager.VariableConverter(@"%appdata%\Citrix\SelfService\Icons\", true)))
                    {
                        FileInfo[] icons = new DirectoryInfo(EnvironmentManager.VariableConverter(@"%appdata%\Citrix\SelfService\Icons\", true)).GetFiles(value("FriendlyName").Replace(" ", "") + "_*.*");
                        if (icons.Length > 0)
                        {
                            string icon = Path.GetFileName(icons.First().FullName);
                            if (icon != null)
                                app.Icon = icon;
                        }
                    }
                    applist.Apps.Add(app);
                });
            }
        }


        /// <summary>
        /// Fügt dem AppListPanel die gewünschte AppListe hinzu und generiert daraus die AppButtons
        /// </summary>
        /// <param name="applist"></param>
        /// <returns></returns>
        async public void CreateButtons(Models.AppList<Models.App> applist)
        {
           flowcontent.Controls.Clear();
            if (_apptype == AppType.Citrix)
            {
                this.GetCitrixApps(applist);
            }
            this.SuspendLayout();
            await Task.Run(async () =>
            {
                if (await XObjects.IsADGroupFinish)
                {
                    try
                    {
                        foreach (var button in this.GetSortedButtons(applist))
                        {
                            this.Invoke(new MethodInvoker(delegate 
                            {
                                this.Controls.Add(button); 
                            }));
                            await Task.Delay(5);
                        }
                        this.Invalidate();
                        if (_apptype == AppType.User)
                            XObjects.LoadingPanel.Loading = false;
                    }
                    catch (Exception ex)
                    {
                        Log.EventLog.Write("AppListPanel CreateButtons", LogClassification.CriticalError, ex);
                    }
                }
            });

            if (this.InvokeRequired)
                this.Invoke(new MethodInvoker(delegate { this.ResumeLayout(); }));
            else
                this.ResumeLayout();
        }


        /// <summary>
        /// Wandelt eine Models.App in einen AppButton für das AppListPanel um
        /// </summary>
        /// <param name="app">Die Models.App aus der die Informationen ausgelesen werden</param>
        /// <returns></returns>
        private AppButton CreateAppButton(Models.App app)
        {
            AppButton appbutton = app.ToAppButton(Cast.IconPath(_apptype, app.Icon), new Padding(Config.User.Apps.Margin));
            appbutton.Size = Config.User.Apps.Size;
            appbutton.AppType = _apptype;
            appbutton.Name = Cast.AppButtonName(_apptype, app);
            appbutton.GroupName = app.Group;
            appbutton.Description = app.Description;
            appbutton.ID = app.ID;
            appbutton.ActiveDirectoryGroups = app.ActiveDirectoryGroups;
            appbutton.Visible = Cast.AppVisibility(app);
            appbutton.Prevalence = Accessor.GetPrevalencia(_apptype, app.ID);
            appbutton.WordWrap = false;
            appbutton.SetDefaultDesign();
            appbutton.Execute = app.Execute;
            appbutton.ImageAlign = AnchorStyles.Left;
            return appbutton;
        }


        /// <summary>
        /// Sortiert die innere Liste der AppButtons nach Beliebtheit, oder Name
        /// </summary>
        public void SortListButtons()
        {
            if (Config.User.Prevalence)
                _sortedlist.Sort(new Comparer.ButtonCompareByPrevalence());
            else
                _sortedlist.Sort(new Comparer.ButtonCompareByName());
            Comparer.SortAllButtons(flowcontent.Controls, Config.User.Prevalence);
        }


        /// <summary>
        /// Fügt dem AppListPanel einen neuen AppButton hinzu
        /// </summary>
        /// <param name="app">Die Models.App App</param>
        public void AddAppButton(Models.App app)
        {
            // --> Er versucht es als Gruppe zu erstellen!!!!
            if (!AddAppToGroupButton(app))
            {
                AppButton appbutton = this.CreateAppButton(app);
                this.Controls.Add(appbutton);
                flowcontent.Controls.SetChildIndex(appbutton, Comparer.SortButton(flowcontent.Controls, appbutton, Config.User.Prevalence));
                _sortedlist.Add(appbutton);
                this.Invalidate(textbounds);
            }
        }


        /// <summary>
        /// Fügt einem bereits bestehenden GroupButton eine neue App hinzu. Wenn bereits eine App mit dem Gruppennamen enthalten ist, wird die Gruppe neu erstellt, 
        /// andernfalls wird der AppButton der bestehenden Gruppe hinzugefügt
        /// </summary>
        /// <param name="app">Die Models.App App</param>
        /// <returns></returns>
        public bool AddAppToGroupButton(Models.App app)
        {
            if (!_grouping || app.Group == null || app.Group == "")
                return false;
            var appstogroupbutton = Accessor.GetAppList(_apptype).Apps.FindAll(modelsapp => modelsapp.Group == app.Group).Union(new Models.App[] { app }).Where(modelsapp => Cast.AppVisibility(modelsapp)).ToArray();

            // Erstellt eine neue Gruppe anhand einer Auflistung von 2 und mehr Models.App mit dem gleichen Gruppennamen. Der GroupButton ist bereits in dem AppListPanel enthalten
            if (_grouping && appstogroupbutton != null && appstogroupbutton.Length > 1 && _sortedlist.OfType<GroupButton>().Select(groupbutton => groupbutton.Name).Contains(Cast.GroupButtonName(_apptype, app.Group)))
            {
                try
                {
                    GroupButton groupbutton = (GroupButton)_sortedlist.Find(button => button.Name == Cast.GroupButtonName(_apptype, app.Group) && button is GroupButton);
                    groupbutton.ContainedApps.Add(app);
                    groupbutton.ContainedAppButtons.Add(this.CreateAppButton(app));
                    return true;
                }
                catch (Exception ex)
                {
                    Log.EventLog.Write($"Konnte App {app.Name} nicht der Gruppe hinzufügen", LogClassification.MediumError, ex);
                    return true;
                }
            }
            // Erstellt eine neue Gruppe, sofern 2 und mehr Models.App mit gleichen Gruppennamen vorhanden sind, jedoch noch kein GroupButton in der AppListPanel enthalten ist
            else if(_grouping && appstogroupbutton.Length == 2)
            {
                try
                {
                    GroupButton groupbutton = this.AddGroupButton(appstogroupbutton);
                    this.Controls.Add(groupbutton);
                    this.RemoveButton(appstogroupbutton[0]);
                    //flowcontent.Controls.SetChildIndex(groupbutton, Comparer.SortButton(flowcontent.Controls, groupbutton, Config.User.Prevalence));
                    return true;
                }
                catch (Exception ex)
                {
                    Log.EventLog.Write("Konnte Gruppe nicht erstellen", LogClassification.MediumError, ex);
                    return true;
                }
            }
            return false;
        }


        /// <summary>
        /// Fügt dem AppListPanel einen neuen GroupButton hinzu
        /// </summary>
        /// <param name="app"></param>
        public GroupButton AddGroupButton(Models.App[] appsToGroupButton)
        {
            GroupButton groupbutton = appsToGroupButton.ToGroupButton(_apptype, new Padding(Config.User.Apps.Margin));
            Prevalencia prevalence = groupbutton.ContainedAppButtons.ToList().Find(app => app.Prevalence.CountClicks == groupbutton.ContainedAppButtons.Max(appbutton => appbutton.Prevalence.CountClicks)).Prevalence;
            groupbutton.Prevalence = prevalence;
            appsToGroupButton.ToList().ForEach(app =>
            {
                flowcontent.Controls.OfType<AppButton>().ToList().RemoveAll(appbutton =>
                {
                    bool check = appbutton.Name == Cast.AppButtonName(_apptype, app);
                    if(check) _sortedlist.Remove(appbutton);
                    return check;
                });
            });
            _sortedlist.Add(groupbutton);
            this.SortListButtons();
            this.Invalidate(textbounds);
            return groupbutton;
        }


        /// <summary>
        /// Löscht den angegebenen GroupButton aus dem AppListPanel. Es kann angegeben werden, ob alle dazugehörigen Apps der Gruppe ebenfalls entfernt werden sollen
        /// </summary>
        /// <param name="name">GroupButton-Name</param>
        /// <param name="removecontainedapps">Sollen alle zugehörigen AppButtons ebenfalls gelöscht werden, oder der letzte AppButton dem AppListPanel hinzugefügt werden</param>
        public void RemoveGroupButton(string name, bool removecontainedapps = false)
        {
            _sortedlist.RemoveAll(button => button.Name == name);
            GroupButton groupbutton = (GroupButton)flowcontent.Controls[name];
            if (groupbutton != null)
            {
                if (removecontainedapps)
                {
                    groupbutton.ContainedApps.Clear();
                    groupbutton.ContainedAppButtons.Clear();
                }
                else if (groupbutton.ContainedApps.Count > 0 && !removecontainedapps)
                {
                    AppButton appbutton_rescued = groupbutton.ContainedAppButtons.First();
                    if (appbutton_rescued.Visible)
                    {
                        this.Controls.Add(appbutton_rescued);
                        _sortedlist.Add(appbutton_rescued);
                    }
                }
            }
            flowcontent.Controls.RemoveByKey(name);
            this.SortListButtons();
        }
        

        /// <summary>
        /// Löscht einen AppButton aus einem AppListPanel anhand des Apptypen und der App aus der JSON-Datei
        /// </summary>
        /// <param name="apptype">Findet anhand des Typen das gewünschte AppListPanel</param>
        /// <param name="app">Die JSON-App mit der der AppButton gefunden und entfernt wird</param>
        public void RemoveButton(Models.App app)
        {
            if (flowcontent.Controls.ContainsKey(Cast.AppButtonName(_apptype, app)))
            {
                Control appbutton = flowcontent.Controls.Find(Cast.AppButtonName(_apptype, app), false)[0];
                flowcontent.Controls.Remove(appbutton);
            }
            else if (_sortedlist.OfType<GroupButton>().ToList().Exists(groupbutton => groupbutton.Name == Cast.GroupButtonName(_apptype, app.Group)))
            {
                GroupButton groupbutton = _sortedlist.OfType<GroupButton>().ToList().Find(groupbtn => groupbtn.Name == Cast.GroupButtonName(_apptype, app.Group));
                groupbutton.RemoveApp(app);
            }
            this.Invalidate(textbounds);
        }


        /// <summary>
        /// Entfernt die Gruppe, sofern nur noch eine App darin enthalten ist
        /// </summary>
        /// <param name="groupbuttonname">Der Schlüsselname des GroupButton. Nicht zu verwechseln mit dem GroupName, also der Eigenschaft GroupButton.Text</param>
        public void RemoveGroupButtonIfNeeded(string groupbuttonname, bool removecontainedapps = false)
        {
            GroupButton groupbutton = _sortedlist.OfType<GroupButton>().ToList().Find(groupbtn => groupbtn.Name == groupbuttonname);
            if (groupbutton != null && groupbutton.ContainedAppButtons.Count(appbutton => appbutton.Visible) == 1)
                this.RemoveGroupButton(groupbuttonname, removecontainedapps);
        }



        /// <summary>
        /// Ersetzt einen AppButton anhand einer bearbeiteten Models.App
        /// </summary>
        /// <param name="replacing_app">Die Models.App App die die überschreibbaren Eigenschaften für den AppButton enthält</param>
        public bool ReplaceButton(Models.App replacing_app)
        {
            bool accepted = false;
            try
            {
                Models.App existing_app = Accessor.GetAppList(_apptype).Apps.Find(app => app.ID == replacing_app.ID);
                AppButton replacing_appbutton = null;
                bool groupexists = _sortedlist.Exists(groupbtn => groupbtn.Name == Cast.GroupButtonName(_apptype, existing_app.Group));
                // Wenn der AppButton in einem GroupButton enthalten ist
                if (groupexists)
                {
                    GroupButton groupbutton = _sortedlist.Find(groupbtn => groupbtn.Name == Cast.GroupButtonName(_apptype, existing_app.Group)) as GroupButton;
                    replacing_appbutton = groupbutton.ContainedAppButtons[groupbutton.ContainedAppButtons.ToList().FindIndex(button => button.Name == Cast.AppButtonName(_apptype, existing_app))];

                    if (replacing_app.Prototype)
                    {
                        //this.RemoveButton(existing_app);
                        replacing_appbutton.Visible = Cast.AppVisibility(replacing_app);
                        this.RemoveGroupButtonIfNeeded(groupbutton.Name, false);
                    }

                    if (replacing_appbutton.GroupName != replacing_app.Group)
                    {
                        this.RemoveButton(existing_app);
                        this.AddAppButton(replacing_app);
                    }
                    
                    groupbutton.Invalidate();
                }
                else
                {                   
                    replacing_appbutton = _sortedlist[_sortedlist.FindIndex(button => button.Name == Cast.AppButtonName(_apptype, existing_app))] as AppButton;
                    this.RemoveButton(existing_app);
                    this.AddAppButton(replacing_app);
                }
                replacing_appbutton.Text = replacing_app.Name;
                replacing_appbutton.Description = replacing_app.Description;
                replacing_appbutton.Execute = replacing_app.Execute;
                replacing_appbutton.Name = Cast.AppButtonName(_apptype, replacing_app);
                replacing_appbutton.Image = File.Exists(Cast.IconPath(_apptype, replacing_app.Icon)) ? Image.FromStream(File.Open(Cast.IconPath(_apptype, replacing_app.Icon), FileMode.Open, FileAccess.Read, FileShare.ReadWrite | FileShare.Delete)) : new Bitmap(1, 1);
                replacing_appbutton.GroupName = replacing_app.Group;
                replacing_appbutton.Visible = !replacing_app.Prototype;
                replacing_appbutton.ActiveDirectoryGroups = replacing_app.ActiveDirectoryGroups;
                accepted = true;
                this.Invalidate(textbounds);
            }
            catch (Exception ex)
            {
                Log.EventLog.Write("AppButton nicht ersetzbar", LogClassification.MediumError, ex);
                accepted = false;
            }
            this.SortListButtons();
            return accepted;
        }


        /// <summary>
        /// Sortiert die AppButtons und GroupButtons nach Beliebtheit, oder Namen
        /// </summary>
        /// <param name="applist"></param>
        /// <returns></returns>
        public List<AppListButton> GetSortedButtons(Models.AppList<Models.App> applist)
        {
            _sortedlist.Clear();

            if (_grouping)
            {
                IEnumerable<IGrouping<string, Models.App>> grouped = (from app in applist.Apps  group app by app.Group);
                grouped.ToList().ForEach(async (group) =>
                {
                    if (group.Count(app => Cast.AppVisibility(app)) >= 2 && group.Key != string.Empty)
                    {
                        this.Invoke(new MethodInvoker(delegate 
                        {
                            try
                            {
                                this.AddGroupButton(group.Select(app => app).ToArray());
                            }
                            catch (Exception ex)
                            {
                                Log.EventLog.Write("Konnte App-Gruppe nicht erstellen", LogClassification.CriticalError, ex);
                            }
                        }));
                        await Task.Delay(1);
                    }
                    else if (group.Count(app => Cast.AppVisibility(app)) < 2 || group.Key == string.Empty)
                    {
                        group.Select(app => app).ToList().ForEach(async app =>
                        {
                            this.Invoke(new MethodInvoker(delegate
                            {
                                try
                                {
                                    AppButton appbutton = this.CreateAppButton(app);
                                    _sortedlist.Add(appbutton);
                                }
                                catch (Exception ex)
                                {
                                    Log.EventLog.Write("Konnte App nicht erstellen", LogClassification.CriticalError, ex);
                                }
                            }));
                            await Task.Delay(1);
                        });
                    }
                });
            }
            else
            {
                applist.Apps.ForEach(async app =>
                {
                    _sortedlist.Add(this.CreateAppButton(app));
                    await Task.Delay(1);
                });
            }
            this.SortListButtons();
            return _sortedlist;
        }


        /// <summary>
        /// Legt die kleinstmögliche Höhe des AppListPanels fest. Dies ist immer die gesamte Höhe des vertikal dargestellten Textes
        /// </summary>
        private void SetMinmimumSize()
        {
            this.MinimumSize = new Size(this.MinimumSize.Width, (int)Math.Floor(TextRenderer.MeasureText(_listname, this.Font).Width * (decimal)1.2));
        }


        /// <summary>
        /// Eine Methode um hinzugefügte Steuerelemente nicht über dem ListName anzuordnen
        /// </summary>
        public void SetListNamePadding()
        {
            this.Padding = new Padding(textbounds.Width, this.Padding.Top, this.Padding.Right, this.Padding.Bottom);
        }


        protected override void OnHandleCreated(EventArgs e)
        {
            base.OnHandleCreated(e);
            this.FindForm().LocationChanged += AppListPanel_LocationChanged;
        }


        private void AppListPanel_LocationChanged(object sender, EventArgs e)
        {
            var _this = sender as FormMain;
            this.Invalidate(textbounds);
        }


        protected override void OnMouseDown(MouseEventArgs e)
        {
            //if(e.Button == MouseButtons.Right)
            //{
            //    this.ContextMenuStrip = new ContextMenuStrip();

            //    var drag = new DragDropDataType("clipboard");
            //    int new_id = AppLists.Favorites.Apps == null || AppLists.Favorites.Apps.Count == 0 ? 1 : AppLists.Favorites.Apps.Max(app => app.ID) + 1;
            //    MessageBox.Show(drag.DragAs.GetDescription());

            //    if (!(drag.DragAs == DragType.Html || drag.DragAs == DragType.Text || drag.DragAs == DragType.Directory))
            //        return;

            //    if (drag.DragAs == DragType.Text || drag.DragAs == DragType.Html)
            //    {
            //        this.ContextMenuStrip.Items.Add("Webseite eingfügen", null, (s, evt) => 
            //        {
            //            // Versucht einen Namen anhand eines Webseiten-Links zu generieren
            //            string name_try = drag.Data.ToString();
            //            if (Config.Main.WebDomains.Any(dom => name_try.Contains(dom)))
            //            {
            //                string domain = Config.Main.WebDomains.First(dom => name_try.Contains(dom));
            //                if (name_try.Contains("http://"))
            //                    name_try = name_try.Substring(name_try.IndexOf("http://"), name_try.LastIndexOf(domain) + domain.Length);
            //                else if (name_try.Contains("https://"))
            //                    name_try = name_try.Substring(name_try.IndexOf("https://"), name_try.LastIndexOf(domain) + domain.Length);
            //                else if (name_try.StartsWith("www."))
            //                    name_try = name_try.Substring(name_try.IndexOf("www."), name_try.LastIndexOf(domain) + domain.Length);
            //                else if (name_try.Where(chr => chr == '/').Count() > 0)
            //                    name_try = name_try.Substring(0, name_try.IndexOf("/"));
            //            }
            //            var msgbox = XObjects.MessageBox("Neuen Namen für die App eingeben", NotifyButtons.OkCancel, NotifyType.TextBox, new Size(350, 150), "Wie soll die App heißen", name_try);
            //            if (msgbox.Result == DialogResult.OK)
            //            {
            //                string sys_webbrowsericon = "webbrowser.png";
            //                string appiconname = msgbox.Value.ToString()
            //                        .Replace(@"\", "_")
            //                        .Replace(@"/", "_")
            //                        .Replace(@":", "_")
            //                        .Replace(@"*", "_")
            //                        .Replace(@"?", "_")
            //                        .Replace("\"", "_")
            //                        .Replace(@"<", "_")
            //                        .Replace(@">", "_")
            //                        .Replace(@"|", "_");

            //                Models.App appnew = new Models.App()
            //                {
            //                    ActiveDirectoryGroups = null,
            //                    Group = "",
            //                    Description = "Öffnet die verlinkte Internetadresse mit dem Microsoft Edge Browser",
            //                    ID = new_id,
            //                    Icon = appiconname,
            //                    Prototype = false,
            //                    Name = msgbox.Value.ToString(),
            //                    Created = DateTime.Now,
            //                    LastModified = DateTime.Now,
            //                    Execute = new Models.Execute[] { new Models.Execute() { Args = "", Command = drag.Data.ToString() } }
            //                };
            //                if (File.Exists($@"{Paths.Icons.Directory}\System\{sys_webbrowsericon}"))
            //                {
            //                    using (FileStream fs_image = new FileStream($@"{Paths.Icons.Directory}\System\{sys_webbrowsericon}", FileMode.Open, FileAccess.Read, FileShare.Delete | FileShare.ReadWrite))
            //                    {
            //                        using (Image img = new Bitmap(fs_image))
            //                        {
            //                            img.Save(Paths.Favorites.Icons.Directory + appiconname);
            //                            AlternateWebbrowser.DrawWebBrowserIcon(img);
            //                        }
            //                    }
            //                }
            //                Creator.AddApp(AppType.Favorites, appnew);
            //            }
            //        });
                    
            //    }
            //    else if (drag.DragAs == DragType.File)
            //    {
            //        this.ContextMenuStrip.Items.Add("Datei verknüpfen", null, (s, evt) =>
            //        {
            //            bool manyfiles = ((string[])drag.Data).Length > 1;
            //            List<Models.App> appstogroup = new List<Models.App>();
            //            ((string[])drag.Data).ToList().ForEach(filename =>
            //            {
            //                string imagename = $"{Path.GetFileNameWithoutExtension(filename)}({Path.GetExtension(filename).Replace(".", "")}).png";
            //                Task.WaitAll(Task.Factory.StartNew(delegate
            //                {
            //                    try
            //                    {
            //                        ((Icon)Icon.ExtractAssociatedIcon(filename)).ToBitmap().Save($@"{Paths.Favorites.Icons.Directory}\{imagename}");
            //                    }
            //                    catch (Exception ex)
            //                    {
            //                        Log.EventLog.Write("Bild nicht gespeichert", LogClassification.LowError, ex);

            //                    }
            //                }));

            //                Models.App appnew = new Models.App()
            //                {
            //                    ActiveDirectoryGroups = null,
            //                    Group = new FileInfo(filename).Directory.Name,
            //                    Description = $"Startet {Path.GetFileName(filename)}",
            //                    ID = AppLists.Favorites.Apps.Max(app => app.ID) + 1,
            //                    Icon = imagename,
            //                    Prototype = false,
            //                    Created = DateTime.Now,
            //                    LastModified = DateTime.Now,
            //                    Name = Path.GetFileName(filename),
            //                    Execute = new Models.Execute[]
            //                    {
            //                new Models.Execute() { Args = "", Command = filename }
            //                    }
            //                };
            //                appstogroup.Add(appnew);
            //                try
            //                {
            //                    Creator.AddApp(AppType.Favorites, appnew);
            //                }
            //                catch (Exception ex)
            //                {
            //                    Log.EventLog.Write("App per Drag'n Drop nicht erstellt", LogClassification.CriticalError, ex);
            //                }
            //            });
            //            if (manyfiles)
            //            {
            //                this.AddGroupButton(appstogroup.ToArray());
            //            }
            //        });
                    
            //    }
            //    else if (drag.DragAs == DragType.Directory)
            //    {
            //        this.ContextMenuStrip.Items.Add("Ordner verknüpfen", null, (s, evt) =>
            //        {
            //            string path = ((string[])drag.Data)[0];
            //            string directoryname = new DirectoryInfo(path).Name;
            //            string icon = "folder.png";
            //            var msgbox = XObjects.MessageBox($"Soll der Ordner gruppiert werden?" +
            //                $"\n\"Ja\": Inhalt wird unter dem Namen \"{directoryname}\" gruppiert." +
            //                $"\n\"Nein\" Öffnet den Ort beim klicken der App im Windows-Explorer", NotifyButtons.YesNoCancel, NotifyType.Message, new Size(400, 200), "Verknüpfung erstellen", null);
            //            if (msgbox.Result == DialogResult.No)
            //            {
            //                Models.App appnew = new Models.App()
            //                {
            //                    ActiveDirectoryGroups = null,
            //                    Group = null,
            //                    Description = $"Öffnet das Verzeichnis \"{directoryname}\"",
            //                    ID = new_id,
            //                    Icon = File.Exists($@"{Paths.Icons.Directory}\System\{icon}") ? icon : null,
            //                    Prototype = false,
            //                    Name = directoryname,
            //                    Created = DateTime.Now,
            //                    LastModified = DateTime.Now,
            //                    Execute = new Models.Execute[]
            //                    {
            //                new Models.Execute() { Args = "", Command = path }
            //                    }
            //                };
            //                if (File.Exists($@"{Paths.Icons.Directory}\System\{icon}"))
            //                    File.Copy($@"{Paths.Icons.Directory}\System\{icon}", Paths.Favorites.Icons.Directory + @"folder.png", true);
            //                Creator.AddApp(AppType.Favorites, appnew);
            //            }
            //            else if (msgbox.Result == DialogResult.Yes)
            //            {
            //                var di = new DirectoryInfo(((string[])drag.Data)[0]);
            //                if (di.GetDirectories().Length > 0)
            //                    File.Copy($@"{Paths.Icons.Directory}\System\{icon}", Paths.Favorites.Icons.Directory + icon, !File.Exists($@"{Paths.Favorites.Icons.Directory}\System\{icon}"));
            //                di.GetDirectories("*", SearchOption.TopDirectoryOnly).ToList().ForEach(dir =>
            //                {
            //                    Models.App appnew = new Models.App()
            //                    {
            //                        ActiveDirectoryGroups = null,
            //                        Group = di.Name,
            //                        Description = $"Öffnet das Verzeichnis \"{dir.Name}\"",
            //                        ID = new_id,
            //                        Icon = File.Exists($@"{Paths.Icons.Directory}\System\{icon}") ? icon : null,
            //                        Prototype = false,
            //                        Name = dir.Name,
            //                        Created = DateTime.Now,
            //                        LastModified = DateTime.Now,
            //                        Execute = new Models.Execute[]
            //                        {
            //                    new Models.Execute() { Args = "", Command = dir.FullName }
            //                        }
            //                    };
            //                    Creator.AddApp(AppType.Favorites, appnew);
            //                    new_id++;
            //                });
            //                di.GetFiles("*", SearchOption.TopDirectoryOnly).ToList().ForEach(file =>
            //                {
            //                    if (file.Name.ToLower() != "thumbs.db")
            //                    {
            //                        string imagename = $"{Path.GetFileNameWithoutExtension(file.Name)}({Path.GetExtension(file.Name).Replace(".", "")}).png";
            //                        try
            //                        {
            //                            Task.WaitAll(Task.Factory.StartNew(delegate
            //                            {
            //                                try
            //                                {
            //                                    Icon.ExtractAssociatedIcon(file.FullName).ToBitmap().Save($@"{Paths.Favorites.Icons.Directory}{imagename}");
            //                                }
            //                                catch (Exception ex)
            //                                {
            //                                    //Log.EventLog.Write($"Symbol von \"{imagename}\" nicht zulässig", LogClassification.LowError, ex);
            //                                }
            //                            }));
            //                        }
            //                        catch (Exception ex)
            //                        {
            //                            Log.EventLog.Write("Bild nicht gespeichert", LogClassification.LowError, ex);
            //                        }


            //                        Models.App appnew = new Models.App()
            //                        {
            //                            ActiveDirectoryGroups = null,
            //                            Group = file.Directory.Name,
            //                            ID = new_id,
            //                            Icon = imagename,
            //                            Name = file.Name,
            //                            Created = DateTime.Now,
            //                            LastModified = DateTime.Now,
            //                            Execute = new Models.Execute[]
            //                            {
            //                    new Models.Execute() { Args = "", Command = file.FullName }
            //                            }
            //                        };
            //                        Creator.AddApp(AppType.Favorites, appnew);
            //                        new_id++;
            //                    }
            //                });
            //            }
            //            path = null;
            //        });
            //        this.ContextMenuStrip.Show(Cursor.Position);
            //    }




            //}
            if(e.Button == MouseButtons.Left)
                mousedown = _resizing && gripbounds.Contains(this.PointToClient(MousePosition));
            base.OnMouseDown(e);
        }


        protected override void OnMouseMove(MouseEventArgs e)
        {
            base.OnMouseMove(e);
            bool gripin = gripbounds.Contains(this.PointToClient(MousePosition));
            if (_resizing && gripin)
            {
                Cursor.Current = Cursors.SizeNS;
            }
            if (mousedown)
            {
                this.Height = this.PointToClient(MousePosition).Y - this.ClientRectangle.Top;
                this.Update();
            }
        }


        protected override void OnMouseUp(MouseEventArgs e)
        {
            if (this.Created)
            {
                if (mousedown)
                {
                    Accessor.GetListProperties(_apptype).Height = this.Height;
                    JSON.Save(JSONConfig.User);
                    Win32API.SendMessage(Forms.Main.Handle, (int)WM.ENTERSIZEMOVE, 0, 0);
                    Win32API.SendMessage(Forms.Main.Handle, (int)WM.EXITSIZEMOVE, 0, 0);
                }
            }
            mousedown = false;
            base.OnMouseUp(e);
        }


        protected override void OnScroll(ScrollEventArgs se)
        {
            base.OnScroll(se);
            if (se.ScrollOrientation == ScrollOrientation.VerticalScroll)
            {
                this.Invalidate();
            }
        }

        protected override void OnMouseWheel(MouseEventArgs e)
        {
            base.OnMouseWheel(e);
            if (this.Created)
            {
                this.Invalidate();
            }
        }


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

            if (this.Height != tempheight && !this.DesignMode)
            {
                textbounds = new Rectangle(new Point(0, 0), new Size((int)Math.Floor(TextRenderer.MeasureText(_listname, this.Font).Height * 1.5), this.Height));
                this.SetListNamePadding();
                tempheight = this.Height;
                if (XObjects.AllAppListPanels != null && XObjects.AllAppListPanels.All(applist => applist.Created))
                {
                    XObjects.AllAppListPanels.ForEach(applist => applist.Update());
                }
                this.Invalidate();
            }
            gripbounds = new Rectangle(this.ClientRectangle.Left, this.ClientRectangle.Bottom - this.Padding.Bottom, this.Width, this.Padding.Bottom);
        }

        protected override void OnFontChanged(EventArgs e)
        {
            base.OnFontChanged(e);
            textbounds = new Rectangle(new Point(0, 0), new Size((int)Math.Floor(TextRenderer.MeasureText(_listname, this.Font).Height * 1.5), this.Height));
            this.SetMinmimumSize();
            this.Invalidate();
        }


        protected override void OnPaddingChanged(EventArgs e)
        {
            base.OnPaddingChanged(e);
            this.Padding = new Padding(
                this.Padding.Left < textbounds.Width ? textbounds.Width : this.Padding.Left,
                this.Padding.Top < _border.Y ? _border.Y : this.Padding.Top,
                this.Padding.Right < _border.X ? _border.X : this.Padding.Right,
                this.Padding.Bottom < _border.Y ? _border.Y : this.Padding.Bottom);
        }

        protected override void OnControlAdded(ControlEventArgs e)
        {
            base.OnControlAdded(e);
            if (e.Control != flowcontent)
            {
                flowcontent.Controls.Add(e.Control);
                this.Controls.Remove(e.Control);
            }
        }


        protected override void OnControlRemoved(ControlEventArgs e)
        {
            if (e.Control != flowcontent)
                flowcontent.Controls.Remove(e.Control);
            base.OnControlRemoved(e);
        }


        protected override void OnPaint(PaintEventArgs e)
        {
            base.OnPaint(e);
            e.Graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
            e.Graphics.TextRenderingHint = System.Drawing.Text.TextRenderingHint.ClearTypeGridFit;
            e.Graphics.DrawString(_listname, this.Font, new SolidBrush(Coloring.GetReadableForeColor(this.BackColor)), textbounds, new StringFormat() { Alignment = StringAlignment.Center, LineAlignment = StringAlignment.Center, FormatFlags = StringFormatFlags.DirectionVertical });
            e.Graphics.DrawLine(new Pen(_bordercolor, _border.X), new Point(textbounds.Right - _border.X, textbounds.Top), new Point(textbounds.Right - _border.X, textbounds.Bottom));
            if (_resizing)
            {
                e.Graphics.DrawLine(new Pen(_bordercolor, _border.Y), new Point(e.ClipRectangle.Left, e.ClipRectangle.Bottom - _border.Y), new Point(e.ClipRectangle.Right, e.ClipRectangle.Bottom - _border.Y));
            }
        }


        protected override void OnDragOver(DragEventArgs drgevent)
        {
            base.OnDragOver(drgevent);
            if (_apptype == AppType.Favorites)
            {
                drgevent.Effect = DragDropEffects.Copy;
                using (Graphics g = flowcontent.CreateGraphics())
                    g.DrawRectangle(new Pen(Config.Main.Colors.Window.Action, Config.Main.Sizes.List.Border.Y) { Alignment = System.Drawing.Drawing2D.PenAlignment.Inset }, new Rectangle(new Point(0, 0), new Size(flowcontent.ClientRectangle.Width - Config.Main.Sizes.List.Border.Y, flowcontent.ClientRectangle.Height - Config.Main.Sizes.List.Border.Y)));
            }
        }

        protected override void OnVisibleChanged(EventArgs e)
        {
            base.OnVisibleChanged(e);
            _showing = Visible;
            if (this.Created)
            {
                Accessor.SetLastAppListPanel();
                Forms.Main.SetMinimumSize();
                Forms.Main.SetStartValue();
                Config.User.Window.Size = Forms.Main.Size;
                JSON.Save(JSONConfig.User);
            }
        }

        protected override void OnDragLeave(EventArgs e)
        {
            base.OnDragLeave(e);
            if (_apptype == AppType.Favorites)
                using (Graphics g = flowcontent.CreateGraphics())
                    g.Clear(this.BackColor);
        }

        protected override void OnDragDrop(DragEventArgs drgevent)
        {
            base.OnDragDrop(drgevent);
            DragDropDataType drag = new DragDropDataType(drgevent);
            int new_id = AppLists.Favorites.Apps == null || AppLists.Favorites.Apps.Count == 0 ? 1 : AppLists.Favorites.Apps.Max(app => app.ID) + 1;

            this.DoDrop(drag, new_id);

            if (_apptype == AppType.Favorites)
                using (Graphics g = flowcontent.CreateGraphics())
                    g.Clear(this.BackColor);
            this.Invalidate(textbounds);
        }


        public void DoDrop(DragDropDataType drag, int new_id)
        {
            Models.App favorite_app = new Models.App();
            if (drag.DragAs == DragType.AppButton)
            {
                try
                {
                    AppButton appproperties = drag.Data as AppButton;
                    favorite_app = new Models.App()
                    {
                        ActiveDirectoryGroups = appproperties.ActiveDirectoryGroups,
                        Execute = new Models.Execute[] {
                            new Models.Execute() {
                                Command = Creator.AppLinkCommand(appproperties.AppType, appproperties.ID)
                            }
                        },
                        //Execute = appproperties.Execute,
                        Group = appproperties.GroupName,
                        Description = appproperties.Description,
                        Icon = appproperties.Image == new Bitmap(1, 1) ? null : Accessor.GetAppList(appproperties.AppType).Apps.Find(app => app.ID == appproperties.ID).Icon,
                        Prototype = !appproperties.Visible,
                        Name = appproperties.Text,
                        Created = DateTime.Now,
                        LastModified = DateTime.Now
                    };

                    if (AppLists.Favorites.Apps.Any(app => app.Name == ((AppButton)drag.Data).Text))
                    {
                        // Wenn der Name der App bereits existiert wird dieser überschrieben
                        Models.App existing_app = AppLists.Favorites.Apps.Find(app => app.Name == ((AppButton)drag.Data).Text);
                        bool differences = false;

                        // Ein vergleich der beiden Apps
                        for (int i = 0; i < existing_app.GetType().GetProperties().Length; i++)
                        {
                            // Existiert eine Veränderung in irgendeiner Eigenschaft, wird gefragt, ob die App ersetzt werden soll
                            if (existing_app.GetType().GetProperties()[i].GetValue(existing_app, null) == null || existing_app.GetType().GetProperties()[i].Name == "ID")
                                continue;
                            System.Reflection.PropertyInfo appdummy = existing_app.GetType().GetProperties()[i];
                            object existing = existing_app.GetType().GetProperties()[i].GetValue(existing_app, null).GetType() == typeof(string[]) ?
                                string.Join("\n", (string[])existing_app.GetType().GetProperties()[i].GetValue(existing_app, null)) :
                                existing_app.GetType().GetProperties()[i].GetValue(existing_app, null).GetType() == typeof(Models.Execute[]) ?
                                string.Join("\n\n", ((Models.Execute[])existing_app.GetType().GetProperties()[i].GetValue(existing_app, null)).Select(exec => exec.Command + "\n" + exec.Args)) :
                                existing_app.GetType().GetProperties()[i].GetValue(existing_app, null);

                            object replacing = (favorite_app.GetType().GetProperties()[i].GetValue(favorite_app, null) == null) ? "" : favorite_app.GetType().GetProperties()[i].GetValue(favorite_app, null).GetType() == typeof(string[]) ?
                                string.Join("\n", (string[])favorite_app.GetType().GetProperties()[i].GetValue(favorite_app, null)) :
                                favorite_app.GetType().GetProperties()[i].GetValue(favorite_app, null).GetType() == typeof(Models.Execute[]) ?
                                string.Join("\n\n", ((Models.Execute[])favorite_app.GetType().GetProperties()[i].GetValue(favorite_app, null)).Select(exec => exec.Command + "\n" + exec.Args)) :
                                favorite_app.GetType().GetProperties()[i].GetValue(favorite_app, null);

                            if (!existing.Equals(replacing))
                            {
                                differences = true;
                                break;
                            }
                        }

                        // Sind keine Unterschiede zwischen der vorhanden und der zu ersetzenden App vorhanden, wird der Vorgang abgebrochen
                        if (!differences)
                            return;

                        var msgbox = XObjects.MessageBox("Der Name der App wird bereits in den Favoriten verwendet. Wenn Sie auf \"Ja\" klicken, wird die App überschrieben. Auf \"Nein\" und es wird eine neue App erstellt", NotifyButtons.YesNoCancel, NotifyType.Message, new Size(300, 200), "App ersetzen durch neue App", null);

                        if (msgbox.Result == DialogResult.Yes)
                        {
                            favorite_app.ID = existing_app.ID;
                            Creator.StreamCopy(Cast.IconPath(appproperties.AppType, Accessor.GetAppList(appproperties.AppType).Apps.Find(app => app.ID == appproperties.ID).Icon), Cast.IconPath(AppType.Favorites, Accessor.GetAppList(appproperties.AppType).Apps.Find(app => app.ID == appproperties.ID).Icon),
                           (stream) =>
                           {
                               Creator.ReplaceApp(AppType.Favorites, favorite_app);
                           });
                        }
                        else if (msgbox.Result == DialogResult.No)
                        {
                            favorite_app.ID = new_id;
                            Creator.StreamCopy(Cast.IconPath(appproperties.AppType, Accessor.GetAppList(appproperties.AppType).Apps.Find(app => app.ID == appproperties.ID).Icon), Cast.IconPath(AppType.Favorites, $"{favorite_app.Name} ({Accessor.GetAppList(_apptype).Apps.Count(app => app.Name.StartsWith(favorite_app.Name))}).png"),
                           (stream) =>
                           {
                               favorite_app.Name += $" ({Accessor.GetAppList(_apptype).Apps.Count(app => app.Name.StartsWith(favorite_app.Name))})";
                               favorite_app.Icon = $"{favorite_app.Name}.png";
                               Creator.AddApp(AppType.Favorites, favorite_app);
                           });
                        }
                        else if (msgbox.Result == DialogResult.Cancel)
                        {
                            return;
                        }
                    }
                    else
                    {
                        // Die App wird automatisch erstellt und / oder gruppiert
                        favorite_app.ID = new_id;
                        File.Copy(Cast.IconPath(appproperties.AppType, Accessor.GetAppList(appproperties.AppType).Apps.Find(app => app.ID == appproperties.ID).Icon), Cast.IconPath(AppType.Favorites, Accessor.GetAppList(appproperties.AppType).Apps.Find(app => app.ID == appproperties.ID).Icon), true);
                        Creator.AddApp(AppType.Favorites, favorite_app);
                    }
                    this.SortListButtons();
                }
                catch (Exception ex)
                {
                    Log.EventLog.Write("DragDropDataType DoDrop - AppButton || FavoriteApp", LogClassification.CriticalError, ex);
                }
            }
            else if (drag.DragAs == DragType.GroupButton)
            {
                try
                {
                    GroupButton clone = (drag.Data as GroupButton);
                    List<Models.App> clones = CloneList(clone.ContainedApps).ToList();
                    string[] usedicons = new string[0];
                    clones.ForEach(app =>
                    {
                        if (!Accessor.GetAppList(AppType.Favorites).Apps.Exists(favapp => favapp.Name == app.Name))
                        {
                            Models.App favorite = new Models.App()
                            {
                                ID = new_id,
                                Description = app.Description,
                                ActiveDirectoryGroups = app.ActiveDirectoryGroups,
                                Created = DateTime.Now,
                                LastModified = DateTime.Now,
                                Execute = new Models.Execute[] { new Models.Execute() { Command = Creator.AppLinkCommand(clone.AppType, app.ID) } },
                                Group = app.Group,
                                Name = app.Name,
                                Icon = app.Icon,
                                Prototype = app.Prototype
                            };
                            try
                            {
                                if (!usedicons.ToList().Exists(icon => icon == app.Icon) && app.Icon != "" && app.Icon != null)
                                {
                                    File.Copy($@"{Paths.Icons.Directory}\{app.Icon}", Paths.Favorites.Icons.Directory + @"\" + app.Icon, true);
                                    Array.Resize(ref usedicons, usedicons.Length + 1);
                                    usedicons[usedicons.Length - 1] = app.Icon;
                                }
                            }
                            catch (Exception ex)
                            {
                                Log.EventLog.Write("Bild nicht gespeichert", LogClassification.LowError, ex);
                            }
                            Creator.AddApp(AppType.Favorites, favorite);
                            new_id++;
                        }
                    });
                    usedicons = null;
                    //this.AddGroupButton(clones.ToArray());
                    this.SortListButtons();
                }
                catch (Exception ex)
                {
                    Log.EventLog.Write("DragDropDataType DoDrop - GroupButton || FavoriteApp", LogClassification.CriticalError, ex);
                }
            }
            else if (drag.DragAs == DragType.Text || drag.DragAs == DragType.Html)
            {
                // Versucht einen Namen anhand eines Webseiten-Links zu generieren
                string name_try = drag.Data.ToString();
                if (Config.Main.WebDomains.Any(dom => name_try.Contains(dom)))
                {
                    string domain = Config.Main.WebDomains.First(dom => name_try.Contains(dom));
                    if (name_try.Contains("http://"))
                        name_try = name_try.Substring(name_try.IndexOf("http://"), name_try.LastIndexOf(domain) + domain.Length);
                    else if (name_try.Contains("https://"))
                        name_try = name_try.Substring(name_try.IndexOf("https://"), name_try.LastIndexOf(domain) + domain.Length);
                    else if (name_try.StartsWith("www."))
                        name_try = name_try.Substring(name_try.IndexOf("www."), name_try.LastIndexOf(domain) + domain.Length);
                    else if (name_try.Where(chr => chr == '/').Count() > 0)
                        name_try = name_try.Substring(0, name_try.IndexOf("/"));
                }
                var msgbox = XObjects.MessageBox("Neuen Namen für die App eingeben", NotifyButtons.OkCancel, NotifyType.TextBox, new Size(350, 150), "Wie soll die App heißen", name_try);
                if (msgbox.Result == DialogResult.OK)
                {
                    string sys_webbrowsericon = "webbrowser.png";
                    string appiconname = msgbox.Value.ToString()
                            .Replace(@"\", "_")
                            .Replace(@"/", "_")
                            .Replace(@":", "_")
                            .Replace(@"*", "_")
                            .Replace(@"?", "_")
                            .Replace("\"", "_")
                            .Replace(@"<", "_")
                            .Replace(@">", "_")
                            .Replace(@"|", "_");

                    Models.App appnew = new Models.App()
                    {
                        ActiveDirectoryGroups = null,
                        Group = "",
                        Description = $"Öffnet die verlinkte Internetadresse {msgbox.Value.ToString()} mit dem Microsoft Edge Browser",
                        ID = new_id,
                        Icon = appiconname,
                        Prototype = false,
                        Name = msgbox.Value.ToString(),
                        Created = DateTime.Now,
                        LastModified = DateTime.Now,
                        Execute = new Models.Execute[] { new Models.Execute() { Args = "", Command = drag.Data.ToString() } }
                    };
                    if (File.Exists($@"{Paths.Icons.Directory}\System\{sys_webbrowsericon}"))
                    {
                        using (FileStream fs_image = new FileStream($@"{Paths.Icons.Directory}\System\{sys_webbrowsericon}", FileMode.Open, FileAccess.Read, FileShare.Delete | FileShare.ReadWrite))
                        {
                            using (Image img = new Bitmap(fs_image))
                            {
                                img.Save(Paths.Favorites.Icons.Directory + appiconname);
                                AlternateWebbrowser.DrawWebBrowserIcon(img);
                            }
                        }
                    }
                    Creator.AddApp(AppType.Favorites, appnew);
                }
            }
            else if (drag.DragAs == DragType.File)
            {
                bool manyfiles = ((string[])drag.Data).Length > 1;
                List<Models.App> appstogroup = new List<Models.App>();
                ((string[])drag.Data).ToList().ForEach(filename =>
                {
                    string imagename = $"{Path.GetFileNameWithoutExtension(filename)}({Path.GetExtension(filename).Replace(".", "")}).png";
                    Task.WaitAll(Task.Factory.StartNew(delegate
                    {
                        try
                        {
                            ((Icon)Icon.ExtractAssociatedIcon(filename)).ToBitmap().Save($@"{Paths.Favorites.Icons.Directory}\{imagename}");
                        }
                        catch (Exception ex)
                        {
                            Log.EventLog.Write("Bild nicht gespeichert", LogClassification.LowError, ex);
                            return;
                        }
                    }));
                    try
                    {
                        Models.App appnew = new Models.App()
                        {
                            ActiveDirectoryGroups = null,
                            Group = new FileInfo(filename).Directory.Name,
                            Description = $"Startet {Path.GetFileName(filename)}",
                            ID = new_id,
                            Icon = imagename,
                            Prototype = false,
                            Created = DateTime.Now,
                            LastModified = DateTime.Now,
                            Name = Path.GetFileName(filename),
                            Execute = new Models.Execute[]
                   {
                            new Models.Execute() { Args = "", Command = filename }
                   }
                        };
                        appstogroup.Add(appnew);
                        Creator.AddApp(AppType.Favorites, appnew);
                    }
                    catch (Exception ex)
                    {
                        Log.EventLog.Write("App per Drag'n Drop nicht erstellt", LogClassification.CriticalError, ex);
                    }
                });
                if (manyfiles)
                {
                    this.AddGroupButton(appstogroup.ToArray());
                }
            }
            else if (drag.DragAs == DragType.Directory)
            {
                string path = ((string[])drag.Data)[0];
                string directoryname = new DirectoryInfo(path).Name;
                string icon = "folder.png";
                var msgbox = XObjects.MessageBox($"Soll der Ordner gruppiert werden?" +
                    $"\n\"Ja\": Inhalt wird unter dem Namen \"{directoryname}\" gruppiert." +
                    $"\n\"Nein\" Öffnet den Ort beim klicken der App im Windows-Explorer", NotifyButtons.YesNoCancel, NotifyType.Message, new Size(400,200), "Verknüpfung erstellen", null);
                if (msgbox.Result == DialogResult.No)
                {
                    Models.App appnew = new Models.App()
                    {
                        ActiveDirectoryGroups = null,
                        Group = null,
                        Description = $"Öffnet das Verzeichnis \"{directoryname}\"",
                        ID = new_id,
                        Icon = File.Exists($@"{Paths.Icons.Directory}\System\{icon}") ? icon : null,
                        Prototype = false,
                        Name = directoryname,
                        Created = DateTime.Now,
                        LastModified = DateTime.Now,
                        Execute = new Models.Execute[]
                        {
                            new Models.Execute() { Args = "", Command = path }
                        }
                    };
                    if (File.Exists($@"{Paths.Icons.Directory}\System\{icon}"))
                        File.Copy($@"{Paths.Icons.Directory}\System\{icon}", Paths.Favorites.Icons.Directory + @"folder.png", true);
                    Creator.AddApp(AppType.Favorites, appnew);
                }
                else if (msgbox.Result == DialogResult.Yes)
                {
                    var di = new DirectoryInfo(((string[])drag.Data)[0]);
                    if (di.GetDirectories().Length > 0)
                        File.Copy($@"{Paths.Icons.Directory}\System\{icon}", Paths.Favorites.Icons.Directory + icon, !File.Exists($@"{Paths.Favorites.Icons.Directory}\System\{icon}"));
                    di.GetDirectories("*", SearchOption.TopDirectoryOnly).ToList().ForEach(dir =>
                    {
                        Models.App appnew = new Models.App()
                        {
                            ActiveDirectoryGroups = null,
                            Group = di.Name,
                            Description = $"Öffnet das Verzeichnis \"{dir.Name}\"",
                            ID = new_id,
                            Icon = File.Exists($@"{Paths.Icons.Directory}\System\{icon}") ? icon : null,
                            Prototype = false,
                            Name = dir.Name,
                            Created = DateTime.Now,
                            LastModified = DateTime.Now,
                            Execute = new Models.Execute[]
                            {
                                new Models.Execute() { Args = "", Command = dir.FullName }
                            }
                        };
                        Creator.AddApp(AppType.Favorites, appnew);
                        new_id++;
                    });
                    di.GetFiles("*", SearchOption.TopDirectoryOnly).ToList().ForEach(file =>
                    {
                        if (file.Name.ToLower() != "thumbs.db")
                        {
                            string imagename = $"{Path.GetFileNameWithoutExtension(file.Name)}({Path.GetExtension(file.Name).Replace(".", "")}).png";
                            try
                            {
                                Task.WaitAll(Task.Factory.StartNew(delegate
                                {
                                    try
                                    {
                                        Icon.ExtractAssociatedIcon(file.FullName).ToBitmap().Save($@"{Paths.Favorites.Icons.Directory}{imagename}");
                                    }
                                    catch (Exception ex)
                                    {
                                        //Log.EventLog.Write($"Symbol von \"{imagename}\" nicht zulässig", LogClassification.LowError, ex);
                                    }
                                }));
                            }
                            catch (Exception ex)
                            {
                                Log.EventLog.Write("Bild nicht gespeichert", LogClassification.LowError, ex);
                            }


                            Models.App appnew = new Models.App()
                            {
                                ActiveDirectoryGroups = null,
                                Group = file.Directory.Name,
                                ID = new_id,
                                Icon = imagename,
                                Name = file.Name,
                                Created = DateTime.Now,
                                LastModified = DateTime.Now,
                                Execute = new Models.Execute[]
                                {
                                new Models.Execute() { Args = "", Command = file.FullName }
                                }
                            };
                            Creator.AddApp(AppType.Favorites, appnew);
                            new_id++;
                        }
                    });
                }
                path = null;
            }
        }


        /// <summary>
        /// Kopiert die Apps einer AppGruppe in eine Liste, ohne die Originale zu verändern
        /// </summary>
        /// <param name="oldList">Die Liste, aus der die Apps entnommen werden</param>
        /// <returns></returns>
        public static IEnumerable<Models.App> CloneList(List<Models.App> oldList)
        {
            foreach (var item in oldList)
            {
                yield return new Models.App() { ID = item.ID, ActiveDirectoryGroups = item.ActiveDirectoryGroups, Execute = item.Execute, Group = item.Group, Icon = item.Icon, Name = item.Name, Prototype = item.Prototype };
            }
        }
    }


    [Browsable(false), ToolboxItem(false)]
    public class FlowContent : FlowLayoutPanel 
    {
        public FlowContent() : base() 
        {
            this.AutoSizeMode = AutoSizeMode.GrowAndShrink;
        }
    } 
}
