﻿using System;
using System.Threading.Tasks;
using System.IO;
using Newtonsoft.Json;
using static Modtorio.FileHelper;
using System.Text;
using System.Linq;
using System.IO.Compression;
using System.Diagnostics;
using ICSharpCode.SharpZipLib.GZip;

namespace Modtorio
{
    public enum ConflictResolving
    {
        Ask, AlwaysYes, AlwaysNo
    }

    public sealed class Settings
    {
        public static Settings Instance
        {
            get
            {
                if (instance == null)
                    instance = new Settings();

                return instance;
            }
        }

        static Settings instance;

        public const string SettingsFile = "settings";

        public string FactorioLocation { get; set; } = "";
        public string FactorioInstallLocation { get; set; } = "";
        public bool AutoEnableMods { get; set; } = true;
        public bool RemoveModsWithoutConfirm { get; set; } = false;
        public bool CheckModsAtStartup { get; set; } = true;
        public bool CompressSettings { get; set; } = true;
        public bool CompressMods { get; set; } = true;
        // TODO: maybe some sort of notifications when mod is replaced/nothing is done
        public ConflictResolving HigherVersionConflictResolving { get; set; } = ConflictResolving.Ask;
        public ConflictResolving LowerVersionConflictResolving { get; set; } = ConflictResolving.AlwaysYes;
        public ConflictResolving SameVersionConflictResolving { get; set; } = ConflictResolving.Ask;

        private Settings()
        {
            LoadSettings();
        }

        void LoadSettings()
        {
            var timer = Stopwatch.StartNew();

            if (!File.Exists(SettingsFile))
            {
                Debug.WriteLine("No settings file found");
                Save();
            }
            else
            {
                using (var fileStream = File.OpenRead(SettingsFile))
                {
                    if (CheckGZipHeader(fileStream))
                    {
                        // TODO: test against .net GZipStream
                        using (var gzip = new GZipInputStream(fileStream))
                        {
                            if (!PopulateFromStream(gzip, this))
                                Debug.WriteLine("Settings loading failed");
                        }
                    }
                    else
                    {
                        if (!PopulateFromStream(fileStream, this))
                            Debug.WriteLine("Settings loading failed");
                    }
                }
            }

            timer.Stop();
            Debug.WriteLine($"Settings loaded in {Math.Round(timer.Elapsed.TotalMilliseconds, 3)}ms");
        }

        public void Save()
        {
            var timer = Stopwatch.StartNew();

            var content = Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(this, Helper.CommonSerialiserSettings));

            if (CompressSettings)
            {
                if (!CompressBytesToFile(content, SettingsFile))
                    Debug.WriteLine("Settings saving failed");
            }
            else
            {
                if (!WriteFileAsync(content, SettingsFile))
                    Debug.WriteLine("Settings saving failed");
            }

            timer.Stop();
            Debug.WriteLine($"Settings saved in {Math.Round(timer.Elapsed.TotalMilliseconds, 3)}ms");
        }
    }
}
