using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System;
using System.Linq;
using System.IO;
using System.Windows.Forms;

namespace GFATask
{
    /// <summary>
    /// Enthält Serialisierungsfunktionen zum Speichern und Auslesen von JSON-Strukturen
    /// </summary>
    public class JSON
    {
        /// <summary>
        /// Speichert das serialisierte Objekt in die angegebene Datei
        /// </summary>
        /// <param name="deserializedJsonObject">Das Objekt welches in die Datei geschrieben werden soll</param>
        /// <param name="path">Pfad zur Datei</param>
        public static void Serialize(object deserializedJsonObject, string path)
        {
            try
            {
                File.WriteAllText(path, JsonConvert.SerializeObject(deserializedJsonObject, new JsonSerializerSettings() { Formatting = Formatting.Indented }));
            }
            catch (System.Exception ex)
            {
                throw ex;
            }
        }

        /// <summary>
        /// Speichert die gewünschte(n) Appsdatei(en) ab
        /// </summary>
        /// <param name="jsonapp">Welche Apps-Datei soll gespeichert werden</param>
        public static void Save(JSONApp jsonapp)
        {
            try
            {
                jsonapp.GetFlags().ToList().ForEach(json =>
                {
                    if ((JSONApp)json == JSONApp.User)
                    {
                        File.WriteAllText(Paths.Apps.Directory + "user.json", JsonConvert.SerializeObject(AppLists.User, new JsonSerializerSettings() { Formatting = Formatting.Indented }));
                    }
                    else if ((JSONApp)json == JSONApp.Admin)
                    {
                        File.WriteAllText(Paths.Apps.Directory + "admin.json", JsonConvert.SerializeObject(AppLists.Admin, new JsonSerializerSettings() { Formatting = Formatting.Indented }));
                    }
                    else if ((JSONApp)json == JSONApp.Menu)
                    {
                        File.WriteAllText(Paths.Apps.Directory + "menu.json", JsonConvert.SerializeObject(AppLists.Menu, new JsonSerializerSettings() { Formatting = Formatting.Indented }));
                    }
                    else if ((JSONApp)json == JSONApp.Favorites)
                    {
                        File.WriteAllText(Paths.Favorites.Apps.FullName, JsonConvert.SerializeObject(AppLists.Favorites, new JsonSerializerSettings() { Formatting = Formatting.Indented }));
                    }
                });

            }
            catch (System.Exception ex)
            {
                Log.EventLog.Write(string.Format("{0} nicht gespeichert", jsonapp.ToString()), LogClassification.CriticalError, ex);
            }
        }

        /// <summary>
        /// Speichert die gewünschte(n) Konfigurationsdatei(en) ab
        /// </summary>
        /// <param name="jsonconfig">Welche Konfigurationsdatei soll gespeichert werden</param>
        public static void Save(JSONConfig jsonconfig)
        {
            try
            {
                jsonconfig.GetFlags().ToList().ForEach(json =>
                {
                    if((JSONConfig)json == JSONConfig.User)
                    {
                        File.WriteAllText(Paths.UserConfig.FullName, JsonConvert.SerializeObject(Config.User, new JsonSerializerSettings() { Formatting = Formatting.Indented }));
                    }
                    else if ((JSONConfig)json == JSONConfig.Main)
                    {
                        File.WriteAllText(Paths.MainConfig.FullName, JsonConvert.SerializeObject(Config.Main, new JsonSerializerSettings() { Formatting = Formatting.Indented }));
                    }
                    else if ((JSONConfig)json == JSONConfig.Prevalence)
                    {
                        File.WriteAllText(Paths.Prevalence.FullName, JsonConvert.SerializeObject(Config.Prevalence, new JsonSerializerSettings() { Formatting = Formatting.Indented }));
                    }
                    else if ((JSONConfig)json == JSONConfig.NewsFeeds)
                    {
                        File.WriteAllText(Paths.NewsFeeds.Values.FullName, JsonConvert.SerializeObject(Config.NewsFeeds, new JsonSerializerSettings() { Formatting = Formatting.Indented }));
                    }
                    else if ((JSONConfig)json == JSONConfig.AppClickCounter)
                    {
                        File.WriteAllText(Paths.AppClickCounter.FullName, JsonConvert.SerializeObject(Config.AppClickCounter, new JsonSerializerSettings() { Formatting = Formatting.Indented }));
                    }
                });

            }
            catch (System.Exception ex)
            {
                Log.EventLog.Write(string.Format("{0} nicht gespeichert", jsonconfig.ToString()), LogClassification.CriticalError, ex);
            }
        }


        /// <summary>
        /// Führt eine Deserialisierung der Json-Datei anhand des Pfades durch
        /// </summary>
        /// <typeparam name="T">Gibt das Model der Serialisierung an</typeparam>
        /// <param name="path">Der Pfad zur Json-Datei die zu einem Objekt serialisiert werden soll</param>
        /// <param name="array">Handelt es sich um eine Array-Datei</param>
        /// <returns>Serialisierter Json-Typ</returns>
        public static T Read<T>(string path, bool array = false)
        {
            try
            {
                if (array)
                {
                    var json = JArray.Parse(File.ReadAllText(path));
                    return JsonConvert.DeserializeObject<T>(json.ToString(), new JsonSerializerSettings() { NullValueHandling = NullValueHandling.Include, Formatting = Formatting.Indented });
                }
                else
                {
                    string json = string.Concat(JObject.Parse(File.ReadAllText(path)));
                    return JsonConvert.DeserializeObject<T>(json, new JsonSerializerSettings() { NullValueHandling = NullValueHandling.Include, Formatting = Formatting.Indented });
                }
            }
            catch (System.Exception ex)
            {
                Log.EventLog.Write(string.Format("{0} nicht einlesbar", Path.GetFileName(path)), LogClassification.Crash, ex);
                throw ex;
            }
        }

        public static bool Exists(string path, string propertyname)
        {
            dynamic jsonobject = JsonConvert.DeserializeObject(string.Concat(JObject.Parse(File.ReadAllText(path))), new JsonSerializerSettings() { NullValueHandling = NullValueHandling.Include, Formatting = Formatting.Indented });
            return ((JObject)jsonobject).Properties().Any(p => p.Name == propertyname);
        }
    }


    /// <summary>
    /// Definiert den JSON-Konfigurations-Dateitypen
    /// </summary>
    [Flags]
    public enum JSONConfig : int
    {
        /// <summary>
        /// Es handelt sich um die Benutzerdefinierte-Konfigurationsdatei
        /// </summary>
        User = 1,

        /// <summary>
        /// Es handelt sich um die Haupt-Konfigurationsdatei
        /// </summary>
        Main = 2,

        /// <summary>
        /// Es handelt sich um die Beliebtheits-Konfigurationsdatei
        /// </summary>
        Prevalence = 4,

        /// <summary>
        /// Es handelt sich um die Neuigkeiten-Konfigurationsdatei
        /// </summary>
        NewsFeeds = 8,

        /// <summary>
        /// Es handelt sich um die AppClickCounter-Konfigurationsdatei
        /// </summary>
        AppClickCounter = 16
    }

    /// <summary>
    /// Definiert den JSON-App-Dateitypen
    /// </summary>
    [Flags]
    public enum JSONApp : int
    {
        /// <summary>
        /// Es handelt sich um die Benutzer-Apps Datei
        /// </summary>
        User = 1,

        /// <summary>
        /// Es handelt sich um die Admin-Apps Datei
        /// </summary>
        Admin = 2,

        /// <summary>
        /// Es handelt sich um die Menü-Apps Datei
        /// </summary>
        Menu = 4,

        /// <summary>
        /// Es handelt sich um die Favoriten-Apps Datei
        /// </summary>
        Favorites = 8
    }
}
