using System;
using System.Collections.Generic;
using System.Drawing;
using System.Globalization;
using System.IO;
using System.Xml.Serialization;

namespace GFATask
{
    /// <summary>
    /// Eine Klasse zur Steuerung der Beliebtheit der App. Je höher der Klickanteil, desto weiter vorne wird der AppButton sortiert
    /// </summary>
    public class Prevalencia
    {
        private int _id = 0;
        /// <summary>
        /// Die eindeutige Identifikationsnummer der App
        /// </summary>
        public int ID { get => _id; set => _id = value; }


        private AppType _apptype = AppType.None;
        /// <summary>
        /// Der Apptyp
        /// </summary>
        public AppType AppType { get => _apptype; set => _apptype = value; }


        private int _countclicks = 0;
        /// <summary>
        /// Wie oft wurde der AppButton angeklickt
        /// </summary>
        public int CountClicks { get => _countclicks; set => _countclicks = value; }


        public Prevalencia() { }

        /// <summary>
        /// Eine Struktur zur Steuerung der Beliebtheit der App. Je höher der Klickanteil, desto weiter vorne wird der AppButton sortiert
        /// </summary>
        /// <param name="id">Die eindeutige Identifikationsnummer der App</param>
        /// <param name="apptype">Der Apptyp</param>
        /// <param name="countclicks">Wie oft wurde der AppButton angeklickt</param>
        public Prevalencia(int id, AppType apptype, int countclicks)
        {
            ID = id;
            AppType = apptype;
            _countclicks = countclicks;
        }


        /// <summary>
        /// Zählt die Klicks hoch und aktualisiert die JSON-Prevalence Konfigurationsdatei
        /// </summary>
        public void CountUp()
        {
            int _id = ID;
            _countclicks++;
            ((List<Models.Prevalence.AppPrevalenceProperties>)Config.Prevalence.GetType().GetProperty(AppType.ToString()).GetValue(Config.Prevalence)).Find(prev => prev.ID == _id).ClickCounts = CountClicks;
            JSON.Save(JSONConfig.Prevalence);
        }
    }


    /// <summary>
    /// Eine Klasse zur Nachverfolgung der angeklickten Apps
    /// </summary>
    public class ClickCounter
    {
        private int _id = 0;
        /// <summary>
        /// Die eindeutige Identifikationsnummer der App
        /// </summary>
        public int ID { get => _id; set => _id = value; }


        private string _name = "";
        /// <summary>
        /// Der Name der App
        /// </summary>
        public string Name { get => _name; set => _name = value; }


        private DateTime _lastclicked;
        /// <summary>
        /// Wann wurde die App zuletzt genutzt
        /// </summary>
        public DateTime LastClicked { get => _lastclicked; set => _lastclicked = value; }


        private DateTime _firstclicked;
        /// <summary>
        /// Wann wurde die App das erste Mal genutzt
        /// </summary>
        public DateTime FirstClicked { get => _firstclicked; set => _firstclicked = value; }


        private AppType _apptype = AppType.None;
        /// <summary>
        /// Der Apptyp
        /// </summary>
        public AppType AppType { get => _apptype; set => _apptype = value; }


        private int _counts = 0;
        /// <summary>
        /// Wie oft wurde der AppButton angeklickt
        /// </summary>
        public int Counts { get => _counts; set => _counts = value; }


        public ClickCounter() { }

        /// <summary>
        /// Eine Klasse zur Nachverfolgung der angeklickten Apps
        /// </summary>
        /// <param name="id">Die eindeutige Identifikationsnummer der App</param>
        /// <param name="apptype">Der Apptyp</param>
        /// <param name="name">Appname</param>
        /// <param name="counts">Anzahl der Benutzerklicks</param>
        public ClickCounter(int id, AppType apptype, string name, int counts, DateTime firstclicked)
        {
            ID = id;
            Name = name;
            AppType = apptype;
            _counts = counts;
            _firstclicked = firstclicked;
            _lastclicked = DateTime.Now;
        }


        /// <summary>
        /// Zählt die Klicks hoch und aktualisiert die JSON-AppClickCounter Konfigurationsdatei
        /// </summary>
        public void CountUp()
        {
            int _id = ID;
            string _name = Name;
            _counts++;
            Models.ClickCounter.AppCounter appcounter = ((List<Models.ClickCounter.AppCounter>)Config.AppClickCounter.GetType().GetProperty(AppType.ToString()).GetValue(Config.AppClickCounter)).Find(cc => cc.ID == _id);
            appcounter.Name = _name;
            appcounter.Counts = _counts;
            appcounter.LastClicked = DateTime.Now;
            JSON.Save(JSONConfig.AppClickCounter);


        }
    }


    /// <summary>
    /// Wandelt das ausführbare Kommando einer verknüpften App in eine lesbare Klasse um
    /// </summary>
    public class AppLnk
    {
        private AppType _apptype = AppType.None;
        /// <summary>
        /// Der Apptyp zur verknüpften App
        /// </summary>
        public AppType AppType { get => _apptype; set => _apptype = value; }


        private int _id = 0;
        /// <summary>
        /// Die eindeutige Identifikationsnummer der verknüpften App
        /// </summary>
        public int ID { get => _id; set => _id = value; }

        public AppLnk() { }

        /// <summary>
        /// Gibt die verknüpfte App aus
        /// </summary>
        /// <returns></returns>
        public Models.App ToApp()
        {
            return Accessor.GetAppList(_apptype).Apps.Find(app => app.ID == _id);
        }
    }


    /// <summary>
    /// Eine Klasse zum Umwandeln in ein lesbares NewsFeed-Objekt
    /// </summary>
    public class ReadableNewsFeed
    {
        /// <summary>
        /// Bestimmt den Namen des NewsFeeds
        /// </summary>
        public string Name { get; }

        /// <summary>
        /// Bestimmt, ob das Objekt angezeigt werden soll
        /// </summary>
        public bool Aktiv { get; }

        /// <summary>
        /// Gibt den Pfad zu dem Symbol an, das anstelle des Grünflächenamts-Logos angezeigt werden soll
        /// </summary>
        public string Symbol { get; }

        /// <summary>
        /// Das anzuzeigende Symbol
        /// </summary>
        public Bitmap Icon { get; }

        /// <summary>
        /// An welchem Tag startet der NewFeed
        /// </summary>
        public int Starttag { get; }

        /// <summary>
        /// In welchem Monat startet der NewsFeed
        /// </summary>
        public int Startmonat { get;  }

        /// <summary>
        /// An welchem Tag endet der NewsFeed
        /// </summary>
        public int Endtag { get;  }

        /// <summary>
        /// In welchem Monat endet der NewsFeed
        /// </summary>
        public int Endmonat { get;  }

        /// <summary>
        /// Zeigt an, was in der Titelleiste dargestellt werden soll
        /// </summary>
        public string Titel { get;  }


        /// <summary>
        /// Klasse zum Umwandeln in ein lesbares NewsFeed-Objekt
        /// </summary>
        /// <param name="newsfeed"></param>
        public ReadableNewsFeed(Models.NewsFeed newsfeed)
        {
            Name = newsfeed.Name;
            Aktiv = newsfeed.Enable;
            Symbol = newsfeed.Icon;
            if (File.Exists($"{Paths.NewsFeeds.Icons.Directory}{newsfeed.Icon}"))
                Icon = new Bitmap(Image.FromStream(File.OpenRead($"{Paths.NewsFeeds.Icons.Directory}{newsfeed.Icon}")), new Size(16, 16));
            else
                Icon = new Bitmap(1, 1);
            Starttag = newsfeed.Begin.Day;
            Startmonat = newsfeed.Begin.Month;
            Endtag = newsfeed.End.Day;
            Endmonat = newsfeed.End.Month;
            Titel = newsfeed.Title;
        }
    }


    /// <summary>
    /// Gibt Informationen einer Backupkonfiguration wieder
    /// </summary>
    public class ConfigBackup : IComparable<ConfigBackup>
    {
        private string _filename = "";
        /// <summary>
        /// Der Dateiname der im Programmpfad liegenden Backupdateien
        /// </summary>
        public string FileName { get => _filename; set => _filename = value; }


        private string _destination_file = "";
        /// <summary>
        /// Der Pfad zur Datei, die im Benutzerpfad ersetzt werden soll
        /// </summary>
        public string DestinationFile { get => _destination_file; set => _destination_file = value; }


        private DateTime _when = default(DateTime);
        /// <summary>
        /// Zu welcher Zeit wurde der Sicherungssatz erstellt
        /// </summary>
        public DateTime When { get => _when; set => _when = value; }


        private ConfigRecoveryType _recoverytype;
        /// <summary>
        /// Um welchen Typen von Sicherung handelt es sich
        /// </summary>
        public ConfigRecoveryType RecoveryType { get => _recoverytype; set => _recoverytype = value; }


        /// <summary>
        /// Gibt Informationen einer Backupkonfiguration wieder
        /// </summary>
        public ConfigBackup() { }

        /// <summary>
        /// Gibt Informationen einer Backupkonfiguration wieder
        /// </summary>
        /// <param name="filename">Dateiname der im Programmpfad liegenden Backupdateien</param>
        public ConfigBackup(string filename)
        {
            _filename = filename;

            _recoverytype = _filename.EndsWith($"_{Path.GetFileNameWithoutExtension(Paths.UserConfig.FullName)}.bak") ? ConfigRecoveryType.UserConfig :
                _filename.EndsWith("_favorites.bak") ? ConfigRecoveryType.Favorites : ConfigRecoveryType.Prevalences;

            _destination_file = _recoverytype == ConfigRecoveryType.UserConfig ? Paths.UserConfig.FullName :
                _recoverytype == ConfigRecoveryType.Favorites ? Paths.Favorites.Apps.FullName : Paths.Prevalence.FullName; 

            string tempdatetime = Path.GetFileNameWithoutExtension(_filename).Trim($"{Environment.UserName.ToLower()}_".ToCharArray());
            _when = DateTime.ParseExact(tempdatetime.Substring(0, 15), "yyyyMMdd-HHmmss", CultureInfo.InvariantCulture);
        }

        /// <summary>
        /// Stellt das Backup wieder her
        /// </summary>
        public void Recover()
        {
            File.Copy(Paths.Bak.Directory + _filename, _destination_file, true);

            //Creator.StreamCopy(Paths.Bak.Directory + _filename, _destination_file, null);
        }


        public int CompareTo(ConfigBackup other)
        {
            return this.When.CompareTo(other.When);
        }
    }


    /// <summary>
    /// Klasse zum Auslesen eines GFATaskStreams, welche über die FrontEndRefresh-Klasse zwischen den gestarteten GFATask-Instanzen synchronisiert wird
    /// </summary>
    [XmlRoot("Object")]
    public class GFATaskStream
    {
        [XmlElement("PipeType")]
        public NetPipeType PipeType { get; set; }


        [XmlElement("ClickCounter")]
        public ClickCounter ClickCounter { get; set; }


        [XmlElement("AppType")]
        public AppType AppType { get; set; }


        [XmlElement("App")]
        public Models.App App { get; set; }
    }
}
