using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Linq;
using System.Security;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using Newtonsoft.Json;

namespace Models
{
    /// <summary>
    /// Modelliert eine App-Liste
    /// </summary>
    [JsonObject(MemberSerialization.OptOut)]
    public class AppList<T>
    {

        /// <summary>
        /// Gibt den enthaltenen App-Typen in der Auflistung an
        /// </summary>
        [JsonProperty("type")]
        public AppType Type
        {
            get;
            set;
        } = AppType.Favorites;

        /// <summary>
        /// Die Auflistung der Apps
        /// </summary>
        [JsonProperty("apps")]
        public List<T> Apps
        {
            get;
            set;
        } = new List<T>();
    }


    /// <summary>
    /// Eine Sammlung von Neuigkeiten für die Titelleiste
    /// </summary>
    [JsonObject(MemberSerialization.OptOut)]
    public class NewsFeed
    {
        [JsonProperty("name")]
        public string Name { get; set; }

        [JsonProperty("enable")]
        public bool Enable { get; set; }

        [JsonProperty("icon")]
        public string Icon { get; set; }

        [JsonProperty("title")]
        public string Title { get; set; }

        [JsonProperty("begin")]
        public Date Begin { get; set; }

        [JsonProperty("end")]
        public Date End { get; set; }


        public class Date
        {
            [JsonProperty("day")]
            public int Day { get; set; }

            [JsonProperty("month")]
            public int Month { get; set; }
        }

        public override string ToString()
        {
            return string.Join("\n", GetType().GetProperties().Select(prop => $@"{prop.Name}: {prop.GetValue(this, null)}"));
        }
    }
    

    /// <summary>
    /// Modelliert die Attribute eines App-Rankings
    /// </summary>
    [JsonObject(MemberSerialization.OptOut)]
    public class Prevalence
    {
        /// <summary>
        /// Beliebtheit der Menü-Apps
        /// </summary>
        [JsonProperty("menu")]
        public List<AppPrevalenceProperties> Menu { get; set; } = new List<AppPrevalenceProperties>();

        /// <summary>
        /// Beliebtheit der Admin-Apps
        /// </summary>
        [JsonProperty("admin")]
        public List<AppPrevalenceProperties> Admin { get; set; } = new List<AppPrevalenceProperties>();

        /// <summary>
        /// Beliebtheit der User-Apps
        /// </summary>
        [JsonProperty("user")]
        public List<AppPrevalenceProperties> User { get; set; } = new List<AppPrevalenceProperties>();

        /// <summary>
        /// Beliebtheit der Citrix-Apps
        /// </summary>
        [JsonProperty("citrix")]
        public List<AppPrevalenceProperties> Citrix { get; set; } = new List<AppPrevalenceProperties>();

        /// <summary>
        /// Beliebtheit der Favoriten-Apps
        /// </summary>
        [JsonProperty("favorites")]
        public List<AppPrevalenceProperties> Favorites { get; set; } = new List<AppPrevalenceProperties>();


        [JsonObject(MemberSerialization.OptOut)]
        public class AppPrevalenceProperties
        {
            /// <summary>
            /// Die eindeutige Identifikationsnummer der ausgeführten App
            /// </summary>
            [JsonProperty("id")]
            public int ID { get; set; }

            /// <summary>
            /// Häufigkeit der Appausführungen und die dadurch automatisierte Sortierung
            /// </summary>
            [JsonProperty("clickcounts")]
            public int ClickCounts { get; set; } = 0;
        }
    }



    /// <summary>
    /// Modelliert die Attribute einer App-Ausführungshäufigkeit
    /// </summary>
    [JsonObject(MemberSerialization.OptOut)]
    public class ClickCounter
    {
        /// <summary>
        /// Ausführungsanzahl der Menü-Apps
        /// </summary>
        [JsonProperty("menu")]
        public List<AppCounter> Menu { get; set; } = new List<AppCounter>();

        /// <summary>
        /// Ausführungsanzahl der Admin-Apps
        /// </summary>
        [JsonProperty("admin")]
        public List<AppCounter> Admin { get; set; } = new List<AppCounter>();

        /// <summary>
        /// Ausführungsanzahl der User-Apps
        /// </summary>
        [JsonProperty("user")]
        public List<AppCounter> User { get; set; } = new List<AppCounter>();


        [JsonObject(MemberSerialization.OptOut)]
        public class AppCounter
        {
            /// <summary>
            /// Die eindeutige Identifikationsnummer der ausgeführten App
            /// </summary>
            [JsonProperty("app_id")]
            public int ID { get; set; }

            /// <summary>
            /// Name der ausgeführten App
            /// </summary>
            [JsonProperty("app_name")]
            public string Name { get; set; }

            /// <summary>
            /// Häufigkeit der Appausführungen
            /// </summary>
            [JsonProperty("counts")]
            public int Counts { get; set; } = 0;

            /// <summary>
            /// Letzte Appausführung
            /// </summary>
            [JsonProperty("lastclicked")]
            public DateTime LastClicked { get; set; }

            /// <summary>
            /// Erste Appausführung
            /// </summary>
            [JsonProperty("firstclicked")]
            public DateTime FirstClicked { get; set; }
        }
    }


    /// <summary>
    /// Modelliert die Attribute einer App
    /// </summary>
    [JsonObject(MemberSerialization.OptOut)]
    public class App
    {
        /// <summary>
        /// Die eindeutige Identifikationsnummer
        /// </summary>
        [JsonProperty("id")]
        public int ID { get; set; }


        /// <summary>
        /// Gibt eine Beschreibung über die App wieder
        /// </summary>
        [JsonProperty("description")]
        public string Description { get; set; }


        /// <summary>
        /// Der Anzeigename der App
        /// </summary>
        [JsonProperty("name")]
        public string Name { get; set; }


        /// <summary>
        /// Gruppierungsname mehrerer Apps für diese App
        /// </summary>
        [JsonProperty("group")]
        public string Group { get; set; }


        /// <summary>
        /// Auflistung von Active Directory Gruppen, die dazu berechtigt sind, die App zu nutzen
        /// </summary>
        [JsonProperty("activedirectory_groups")]
        public string[] ActiveDirectoryGroups { get; set; }


        /// <summary>
        /// Bestimmt, ob es sich um einen Prototypen handelt. Diese App wird nur für Admins angezeigt und erst mit deaktivieren dieser Eigenschaft für alle Berechtigten sichtbar
        /// </summary>
        [JsonProperty("prototype")]
        public bool Prototype { get; set; }


        /// <summary>
        /// Ausführungsbefehle und optionale Argumente welche der Reihe nach ausgeführt werden, sofern diese fehlschlagen
        /// </summary>
        [JsonProperty("exec")]
        public Execute[] Execute { get; set; }


        /// <summary>
        /// Gibt den Pfad zum Symbol der App an
        /// </summary>
        [JsonProperty("icon")]
        public string Icon { get; set; }


        /// <summary>
        /// Gibt den Pfad zum Symbol der App an
        /// </summary>
        [JsonProperty("lastmodified")]
        public DateTime LastModified { get; set; }


        /// <summary>
        /// Gibt den Pfad zum Symbol der App an
        /// </summary>
        [JsonProperty("created")]
        public DateTime Created { get; set; }


        /// <summary>
        /// Erstelle eine Kopie des App-Objekts
        /// </summary>
        /// <returns></returns>
        public App Copy()
        {
            return (App)this.MemberwiseClone();
        }

        /// <summary>
        /// Gibt das App-Modell in einer lesbaren Zeichenfolge aus
        /// </summary>
        /// <returns></returns>
        new public virtual string ToString()
        {
            return string.Join("\n", from property in this.GetType().GetProperties() select property.Name + ": " + property.GetValue(this, null));
        }
    }


    /// <summary>
    /// Modelliert eine Ausführungsfunktion für eine App
    /// </summary>
    [JsonObject(MemberSerialization.OptOut)]
    public class Execute
    {
        [JsonProperty("cmd")]
        public string Command { get; set; }

        [JsonProperty("args")]
        public string Args { get; set; }

        new public virtual string ToString()
        {
            return string.Join("\n", from property in this.GetType().GetProperties() select property.Name + ": " + property.GetValue(this, null));
        }
    }


    /// <summary>
    /// Serialisiert die Json-Configs
    /// </summary>
    public class Config
    {
        [JsonObject(MemberSerialization.OptOut)]
        public class Main
        {
            [JsonProperty("defaultwebbrowser")]
            public string DefaultWebBrowser
            {
                get;
                set;
            } = "Microsoft Edge";


            [JsonProperty("webdomains")]
            public string[] WebDomains
            {
                get;
                set;
            }


            [JsonProperty("domainname")]
            public string DomainName
            {
                get;
                set;
            }

            [JsonProperty("loggerapppath")]
            public string LoggerAppPath
            {
                get;
                set;
            }

            [JsonProperty("citrix")]
            public CitrixProperties Citrix
            {
                get;
                set;
            }


            [JsonProperty("use_ad_groups")]
            public bool UseActiveDirectoryGroups { get; set; }


            [JsonProperty("administration")]
            public AdministrationProperties Administration
            {
                get;
                set;
            }


            [JsonProperty("font")]
            public string FontFamily
            {
                get;
                set;
            }


            [JsonProperty("colors")]
            public ColorsProperties Colors
            {
                get;
                set;
            }


            [JsonProperty("sizes")]
            public SizesProperties Sizes
            {
                get;
                set;
            }

            [EditorBrowsable(EditorBrowsableState.Never)]
            [JsonObject(MemberSerialization.OptOut)]
            public class SizesProperties
            {
                [JsonProperty("window")]
                public WindowProperties Window
                {
                    get;
                    set;
                }

                [JsonProperty("list")]
                public ListSizeProperties List
                {
                    get;
                    set;
                }
            }

            [EditorBrowsable(EditorBrowsableState.Never)]
            [JsonObject(MemberSerialization.OptOut)]
            public class WindowProperties
            {
                [JsonProperty("radius")]
                public int Radius
                {
                    get;
                    set;
                }

                [JsonProperty("border")]
                public int Border
                {
                    get;
                    set;
                }
            }

            [EditorBrowsable(EditorBrowsableState.Never)]
            [JsonObject(MemberSerialization.OptOut)]
            public class ListSizeProperties
            {
                [JsonProperty("border")]
                public Point Border
                {
                    get;
                    set;
                }
            }

            [EditorBrowsable(EditorBrowsableState.Never)]
            [JsonObject(MemberSerialization.OptOut)]
            public class AppProperties
            {
                [JsonProperty("radius")]
                public int Radius
                {
                    get;
                    set;
                }

                [JsonProperty("margin")]
                public int Margin
                {
                    get;
                    set;
                }
            }


            [EditorBrowsable(EditorBrowsableState.Never)]
            [JsonObject(MemberSerialization.OptOut)]
            public class CitrixProperties
            {
                [JsonProperty("xmlnodes")]
                public string XMLNodes { get; set; }

                [JsonProperty("icons")]
                public string Icons { get; set; }

                [JsonProperty("icaselfservice")]
                public string ICASelfService { get; set; }

                [JsonProperty("appslocation")]
                public string AppsLocation { get; set; }
            }


            [EditorBrowsable(EditorBrowsableState.Never)]
            [JsonObject(MemberSerialization.OptOut)]
            public class AdministrationProperties
            {
                [JsonProperty("remote_frontend_update")]
                public bool RemoteFrontEndUpdate { get; set; }


                [JsonProperty("ad_group")]
                public string ActiveDirectoryGroup { get; set; }


                [JsonProperty("accounts")]
                public AccountProperties Accounts { get; set; }


                [EditorBrowsable(EditorBrowsableState.Never)]
                [JsonObject(MemberSerialization.OptOut)]
                public class AccountProperties
                {
                    [JsonProperty("mailaccount")]
                    public MailAccount Mail { get; set; }

                    [JsonProperty("adminlogin")]
                    public AdminLogin Login { get; set; }


                    [EditorBrowsable(EditorBrowsableState.Never)]
                    [JsonObject(MemberSerialization.OptOut)]
                    public class MailAccount
                    {
                        [JsonProperty("host")]
                        public string Host { get; set; }

                        [JsonProperty("sslport")]
                        public int SSLPort { get; set; }


                        [JsonProperty("username")]
                        public string UserName { get; set; }


                        [JsonProperty("securepassword")]
                        public int[] SecurePassword { get; set; }


                        [JsonProperty("mailmessage")]
                        public MailMessageProperties MailMessage { get; set; }


                        [EditorBrowsable(EditorBrowsableState.Never)]
                        [JsonObject(MemberSerialization.OptOut)]
                        public class MailMessageProperties
                        {
                            [JsonProperty("to")]
                            public string To { get; set; }


                            [JsonProperty("from")]
                            public FromProperties From { get; set; }


                            [EditorBrowsable(EditorBrowsableState.Never)]
                            [JsonObject(MemberSerialization.OptOut)]
                            public class FromProperties
                            {
                                [JsonProperty("address")]
                                public string Address { get; set; }

                                [JsonProperty("displayname")]
                                public string DisplayName { get; set; }
                            }
                        }

                    }


                    [EditorBrowsable(EditorBrowsableState.Never)]
                    [JsonObject(MemberSerialization.OptOut)]
                    public class AdminLogin
                    {
                        [JsonProperty("securepassword")]
                        public int[] SecurePassword { get; set; }
                    }
                }
            }


            [EditorBrowsable(EditorBrowsableState.Never)]
            [JsonObject(MemberSerialization.OptOut)]
            public class ColorsProperties
            {
                [JsonProperty("loadinganimation")]
                public LoadingAnimationColorProperties LoadingAnimation
                {
                    get;
                    set;
                }

                [JsonProperty("list")]
                public ListColorProperties List
                {
                    get;
                    set;
                }

                [JsonProperty("window")]
                public WindowProperties Window
                {
                    get;
                    set;
                }


                [JsonProperty("groupwindow")]
                public WindowProperties GroupWindow
                {
                    get;
                    set;
                } = new WindowProperties();


                [JsonProperty("apps")]
                public AppsProperties Apps
                {
                    get;
                    set;
                }


                [EditorBrowsable(EditorBrowsableState.Never)]
                [JsonObject(MemberSerialization.OptOut)]
                public class LoadingAnimationColorProperties
                {
                    [JsonProperty("dot1")]
                    public Color Dot1
                    {
                        get;
                        set;
                    }

                    [JsonProperty("dot2")]
                    public Color Dot2
                    {
                        get;
                        set;
                    }

                    [JsonProperty("dot3")]
                    public Color Dot3
                    {
                        get;
                        set;
                    }

                    [JsonProperty("dot4")]
                    public Color Dot4
                    {
                        get;
                        set;
                    }
                }


                [EditorBrowsable(EditorBrowsableState.Never)]
                [JsonObject(MemberSerialization.OptOut)]
                public class ListColorProperties
                {
                    [JsonProperty("border")]
                    public Color Border
                    {
                        get;
                        set;
                    }
                }


                    [EditorBrowsable(EditorBrowsableState.Never)]
                [JsonObject(MemberSerialization.OptOut)]
                public class WindowProperties
                {
                    [JsonProperty("backcolor")]
                    public Color BackColor
                    {
                        get;
                        set;
                    }

                    [JsonProperty("action")]
                    public Color Action
                    {
                        get;
                        set;
                    } = Color.Orange;


                    [JsonProperty("titlebarbackcolor")]
                    public Color TitlebarBackColor
                    {
                        get;
                        set;
                    }


                    [JsonProperty("border")]
                    public Color Border
                    {
                        get;
                        set;
                    }
                }


                [EditorBrowsable(EditorBrowsableState.Never)]
                [JsonObject(MemberSerialization.OptOut)]
                public class AppsProperties
                {
                    [JsonProperty("default")]
                    public ColorsAppsProperties Default
                    {
                        get;
                        set;
                    }

                    [JsonProperty("hover")]
                    public ColorsAppsProperties Hover
                    {
                        get;
                        set;
                    }


                    [EditorBrowsable(EditorBrowsableState.Never)]
                    [JsonObject(MemberSerialization.OptOut)]
                    public class ColorsAppsProperties
                    {
                        [JsonProperty("backcolor")]
                        public Color BackColor
                        {
                            get;
                            set;
                        }

                        [JsonProperty("forecolor")]
                        public Color ForeColor
                        {
                            get;
                            set;
                        }

                        [JsonProperty("border")]
                        public Color Border
                        {
                            get;
                            set;
                        }


                        [JsonProperty("image")]
                        public Color Image
                        {
                            get;
                            set;
                        }
                    }
                }
            }
        }


        [JsonObject(MemberSerialization.OptOut)]
        public class User
        {
            /// <summary>
            /// Soll der GFATask im Dark Mode dargestellt werden
            /// </summary>
            [
                Description("Soll der GFATask im Dark Mode dargestellt werden"),
                JsonProperty("darkmode")
            ]
            public bool DarkMode { get; set; } = false;


            /// <summary>
            /// Bestimmt, ob zum Einblenden des GFA-Task ein Klick benötigt wird. Verhindert das der GFA-Task beim berühren des oberen Bildschirmrands eingeblendet wird
            /// </summary>
            [
                Description("Bestimmt, ob zum Einblenden des GFA-Task ein Klick benötigt wird. Verhindert das der GFA-Task beim berühren des oberen Bildschirmrands eingeblendet wird"),
                JsonProperty("necessary_click")
            ]
            public bool NecessaryClick { get; set; } = false;


            /// <summary>
            /// Bestimmt, ob bei der Sortierung der Apps nach Beliebtheit, oder Name vorgegangen wird
            /// </summary>
            [
                Description("Bestimmt, ob bei der Sortierung der Apps nach Beliebtheit, oder Name vorgegangen wird"),
                JsonProperty("prevalence")
            ]
            public bool Prevalence { get; set; } = false;


            /// <summary>
            /// Bestimmt, ob die Ereiginisanzeige zur Fehleranalyse beim start des GFA-Task mitgestartet werden soll
            /// </summary>
            [
                Description("Bestimmt, ob die Ereiginisanzeige zur Fehleranalyse beim start des GFA-Task mitgestartet werden soll"),
                JsonProperty("autostart_eventlogger")
            ]
            public bool ErrorHandle { get; set; } = false;


            /// <summary>
            /// Bestimmt, wie beim Programmstart mit den benutzerdefinierten Dateien umgegangen werden soll
            /// </summary>
            [
                Description("Bestimmt, wie beim Programmstart mit den benutzerdefinierten Dateien umgegangen werden soll"),
                JsonProperty("deploy")
            ]
            public DeployProperties Deploy { get; set; } = new DeployProperties() { Backup = true, Overwrite = true };


            /// <summary>
            /// Definiert den Bildschirm, auf dem der GFA-Task dargestellt werden soll
            /// </summary>
            [
                Description("Definiert den Bildschirm, auf dem der GFA-Task dargestellt werden soll"),
                JsonProperty("screen")
            ]
            public string Screen { get; set; } = "DISPLAY1";


            /// <summary>
            /// Definiert die Wartezeiten und Geschwindigkeit des Ein- und Ausblendprozesses des GFA-Tasks
            /// </summary>
            [
                Description("Definiert die Wartezeiten und Geschwindigkeit des Ein- und Ausblendprozesses des GFA-Tasks"),
                JsonProperty("delay")
            ]
            public DelayProperties Delay { get; set; } = new DelayProperties() { Hide = 0.5F, Show = 0.5F, Speed = 70 };


            ///// <summary>
            ///// 
            ///// </summary>
            //[JsonProperty("locations")]
            //public LocationProperties Locations { get; set; }


            /// <summary>
            /// Stellt den GFA-Task nach den gewünschten Eigenschaften dar
            /// </summary>
            [
                Description("Stellt den GFA-Task nach den gewünschten Eigenschaften dar"),
                JsonProperty("window")
            ]
            public WindowProperties Window { get; set; } = new WindowProperties() { FontSize = 9F, Opacity = .95D, Size = new Size(940, 420) };


            /// <summary>
            /// Stellt die Apps nach den gewünschten Eigenschaften dar
            /// </summary>
            [
                Description("Stellt die Apps nach den gewünschten Eigenschaften dar"),
                JsonProperty("apps")
            ]
            public AppsProperties Apps { get; set; } = new AppsProperties() { Border = 0, Margin = 3, Size = new Size(140, 35), ImageOnly = false, Radius = new AppsProperties.RadiusProperties() { Button = 3, Image = 5 } };


            /// <summary>
            /// Stellt die Listen nach den gewünschten Eigenschaften dar
            /// </summary>
            [
                Description("Stellt die Listen nach den gewünschten Eigenschaften dar"),
                JsonProperty("lists")
            ]
            public ListsProperties Lists { get; set; } = new ListsProperties()
            {
                Admin = new ListProperties() { Grouping = true, Height = 100, Show = false },
                Citrix = new ListProperties() { Grouping = true, Height = 100, Show = false },
                Favorites = new ListProperties() { Grouping = true, Height = 55, Show = true },
                Menu = new ListProperties() { Grouping = true, Height = 55, Show = true },
                User = new ListProperties() { Grouping = true, Height = 100, Show = true }
            };


            /// <summary>
            /// Bestimmt beim Öffnen einer App-Gruppe, wie viele Apps in einer Zeile angezeigt werden sollen, bis in die nächste Zeile umgebrochen werden soll
            /// </summary>
            [
                Description("Bestimmt beim Öffnen einer App-Gruppe, wie viele Apps in einer Zeile angezeigt werden sollen, bis in die nächste Zeile umgebrochen werden soll"),
                JsonProperty("grouplistcolumncount")
            ]
            public int GroupListColumnCount { get; set; } = 3;



            [EditorBrowsable(EditorBrowsableState.Never)]
            [JsonObject(MemberSerialization.OptOut)]
            public class DeployProperties
            {
                [JsonProperty("overwrite")]
                public bool Overwrite
                {
                    get;
                    set;
                }

                [JsonProperty("backup")]
                public bool Backup
                {
                    get;
                    set;
                }

                new public virtual string ToString()
                {
                    return string.Join("\n", from property in this.GetType().GetProperties() select property.Name + ": " + property.GetValue(this, null));
                }
            }


            [EditorBrowsable(EditorBrowsableState.Never)]
            [JsonObject(MemberSerialization.OptOut)]
            public class DelayProperties
            {
                [JsonProperty("speed")]
                public int Speed
                {
                    get;
                    set;
                }


                [JsonProperty("show")]
                public float Show
                {
                    get;
                    set;
                }


                [JsonProperty("hide")]
                public float Hide
                {
                    get;
                    set;
                }


                new public virtual string ToString()
                {
                    return string.Join("\n", from property in this.GetType().GetProperties() select property.Name + ": " + property.GetValue(this, null));
                }
            }


            [EditorBrowsable(EditorBrowsableState.Never)]
            [JsonObject(MemberSerialization.OptOut)]
            public class ListsProperties
            {
                [JsonProperty("menu")]
                public ListProperties Menu { get; set; }


                [JsonProperty("citrix")]
                public ListProperties Citrix { get; set; }


                [JsonProperty("favorites")]
                public ListProperties Favorites { get; set; }


                [JsonProperty("admin")]
                public ListProperties Admin { get; set; }


                [JsonProperty("user")]
                public ListProperties User { get; set; }
            }


            [EditorBrowsable(EditorBrowsableState.Never)]
            [JsonObject(MemberSerialization.OptOut)]
            public class WindowProperties
            {
                [JsonProperty("size")]
                public Size Size { get; set; }

                [JsonProperty("actionregionheight")]
                public int ActionRegionHeight { get; set; } = 3;

                [JsonProperty("font")]
                public float FontSize { get; set; }

                [JsonProperty("opacity")]
                public double Opacity { get; set; }

            }


            [EditorBrowsable(EditorBrowsableState.Never)]
            [JsonObject(MemberSerialization.OptOut)]
            public class AppsProperties
            {
                [JsonProperty("imageonly")]
                public bool ImageOnly { get; set; }

                [JsonProperty("border")]
                public int Border { get; set; }

                [JsonProperty("size")]
                public Size Size { get; set; }

                [JsonProperty("margin")]
                public int Margin { get; set; }

                [JsonProperty("radius")]
                public RadiusProperties Radius { get; set; }


                [EditorBrowsable(EditorBrowsableState.Never)]
                [JsonObject(MemberSerialization.OptOut)]
                public class RadiusProperties
                {
                    [JsonProperty("button")]
                    public int Button { get; set; }

                    [JsonProperty("image")]
                    public int Image { get; set; }
                }
            }


            [EditorBrowsable(EditorBrowsableState.Never)]
            [JsonObject(MemberSerialization.OptOut)]
            public class ListProperties
            {
                [JsonProperty("height")]
                public int Height { get; set; } = 96;

                [JsonProperty("show")]
                public bool Show { get; set; } = false;

                [JsonProperty("grouping")]
                public bool Grouping { get; set; } = false;
            }

            new public virtual string ToString()
            {
                return string.Join("\n", from property in this.GetType().GetProperties() select property.Name + ": " + property.GetValue(this, null));
            }
        }
    }
}
