﻿using System;
using System.IO;
using Newtonsoft.Json;
using UnityEngine;

namespace FiniteItemRepairs
{
    public static class Settings
    {
        [JsonObject (MemberSerialization.Fields)]
        public class SettingsData
        {
            private float degradationPercent = 0.5f;
            public float DegradationPercent
            {
                get => degradationPercent;
                set
                {
                    if (Mathf.Approximately(value, degradationPercent))
                    {
                        return;
                    }

                    degradationPercent = Mathf.Clamp01(value);
                    Save();
                }
            }
        }

        public static SettingsData Data { get; private set; }

        private static bool initDone;


        public static void Init()
        {
            if (initDone)
            {
                return;
            }

            initDone = true;
            InitFileWatcher();
            Load();
        }

#region IO

        private static readonly string ConfigFileName = $"{ModMain.Mod.Name}_Settings.json";

        private static FileSystemWatcher fileWatcher;

        private static void InitFileWatcher()
        {
            fileWatcher = new FileSystemWatcher(GetFilePath(), ConfigFileName);
            fileWatcher.Changed += OnFileChanged;
            fileWatcher.Created += OnFileChanged;
            fileWatcher.Deleted += OnFileChanged;
            fileWatcher.EnableRaisingEvents = true;
        }

        public static void DestroyFileWatcher()
        {
            if (fileWatcher == null)
            {
                return;
            }

            fileWatcher.Dispose();
            fileWatcher = null;
        }

        private static void OnFileChanged(object source, FileSystemEventArgs e)
        {
            Log.Out($"[MOD] [{ModMain.Mod.DisplayName}] Reloading {ConfigFileName}");
            Load();
        }

        private static string GetFilePath()
        {
            return GameIO.GetUserGameDataDir();
        }

        private static string GetFullPath()
        {
            return $"{GetFilePath()}/{ConfigFileName}";
        }

        private static void Load()
        {
            if (!SdFile.Exists(GetFullPath()))
            {
                Log.Out($"[MOD] [{ModMain.Mod.DisplayName}] config file '{ConfigFileName}' not found, creating.");
                Data = new SettingsData();
                Save();
                return;
            }

            Log.Out($"[MOD] [{ModMain.Mod.DisplayName}] Loading config file from '{GetFullPath()}'");

            try
            {
                string jsonText = SdFile.ReadAllText(GetFullPath());
                Data = JsonConvert.DeserializeObject<SettingsData>(jsonText);
            }
            catch (JsonException e)
            {
                Log.Error($"[MOD] [{ModMain.Mod.DisplayName}] Exception while trying to load config file:");
                Log.Exception(e);

                Data = new SettingsData();
                Save();
            }
        }

        public static void Save()
        {
            try
            {
                string jsonText = JsonConvert.SerializeObject(Data);

                fileWatcher.EnableRaisingEvents = false;
                SdFile.WriteAllText(GetFullPath(), jsonText);
                fileWatcher.EnableRaisingEvents = true;

                Log.Out($"[MOD] [{ModMain.Mod.DisplayName}] Saved config file to '{GetFullPath()}'.");
            }
            catch (Exception e)
            {
                Log.Error($"[MOD] [{ModMain.Mod.DisplayName}] Exception while trying to save config file to '{GetFullPath()}':");
                Log.Exception(e);
            }
        }

#endregion
    }
}