using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Windows.Forms;
using TweetDuck.Controls;
using TweetDuck.Dialogs;
using TweetLib.Core.Application;

namespace TweetDuck.Resources{
    class ScriptLoader : IAppResourceHandler{
        private readonly Dictionary<string, string> cache = new Dictionary<string, string>(16);
        private Control sync;

        public void Initialize(Control sync){
            this.sync = sync;
        }

        protected void ClearCache(){
            cache.Clear();
        }

        public virtual void OnReloadTriggered(){
            if (Control.ModifierKeys.HasFlag(Keys.Shift)){
                ClearCache();
            }
        }

        public string Load(string path)       => LoadInternal(path, silent: false);
        public string LoadSilent(string path) => LoadInternal(path, silent: true);

        protected virtual string LocateFile(string path){
            return Path.Combine(Program.ScriptPath, path);
        }

        private string LoadInternal(string path, bool silent){
            if (sync == null){
                throw new InvalidOperationException("Cannot use ScriptLoader before initialization.");
            }
            else if (sync.IsDisposed){
                return null; // better than crashing I guess...?
            }

            if (cache.TryGetValue(path, out string resourceData)){
                return resourceData;
            }

            string location = LocateFile(path);
            string resource;

            try{
                string contents = File.ReadAllText(location, Encoding.UTF8);
                int separator;

                // first line can be either:
                // #<version>\r\n
                // #<version>\n

                if (contents[0] != '#'){
                    ShowLoadError(silent ? null : sync, $"File {path} appears to be corrupted, please try reinstalling the app.");
                    separator = 0;
                }
                else{
                    separator = contents.IndexOf('\n');
                    string fileVersion = contents.Substring(1, separator - 1).TrimEnd();

                    if (fileVersion != Program.VersionTag){
                        ShowLoadError(silent ? null : sync, $"File {path} is made for a different version of TweetDuck ({fileVersion}) and may not function correctly in this version, please try reinstalling the app.");
                    }
                }

                resource = contents.Substring(separator).TrimStart();
            }catch(Exception ex){
                ShowLoadError(silent ? null : sync, $"Could not load {path}. The program will continue running with limited functionality.\n\n{ex.Message}");
                resource = null;
            }

            return cache[path] = resource;
        }

        private static void ShowLoadError(Control sync, string message){
            sync?.InvokeSafe(() => FormMessage.Error("Resource Error", message, FormMessage.OK));
        }
    }
}