using System;
using System.Collections.Generic;
using SGModule.Common;
using SGModule.Common.Base;
using SGModule.Common.Helper;

namespace SGModule.ConfigLoader {
    public class ConfigLoader : SingletonMonoBehaviour<ConfigLoader> {
        private readonly ConfigDataManager _dataManager = new();
        private readonly ConfigFileManager _fileManager = new();
        private ConfigInitOptions _initOptions;
        private bool _isConfigLoaded;


        public void Init(ConfigInitOptions options) {
            _initOptions = options ?? throw new ArgumentNullException(nameof(options));
            IsInitComplete = true;

            Log.ConfigLoader.Info("Setting: " + _initOptions.Setting);

            _fileManager.CheckAndLoadConfig(_initOptions, ReloadConfig, state => {
                if (state == ConfigLoaderState.Successful) {
                    Log.ConfigLoader.Info($"Data read successfully: {SerializeHelper.ToJsonIndented(GetJsonKeys())}", false);
                    ConfigParser.ParseAllConfigs(new ParseConfigOptions {
                        OnParsed = (type, instance) => _dataManager.AddConfig(type, instance),
                        OnError = _initOptions.OnError,
                        OnHandleUnmarkedConfig = _initOptions.OnHandleUnmarkedConfig
                    });
                }

                _initOptions.OnComplete?.Invoke(state);
            });
        }

        private void ReloadConfig(string json) {
            if (string.IsNullOrWhiteSpace(json)) {
                return;
            }

            if (!json.StartsWith("{")) {
                json = Cryptor.Decrypt(json, ConfigManager.GameConfig.packageName);
            }

            _dataManager.SetJsonDictionary(json);
            _isConfigLoaded = true;
        }


        public T GetConfig<T>() where T : class {
            return _dataManager.GetConfig<T>();
        }

        public void AddConfig(object configModel) {
            _dataManager.AddConfig(configModel);
        }

        public bool TryGetJsonValue(string key, out object value) {
            return _dataManager.TryGetJsonValue(key, out value);
        }

        public IEnumerable<string> GetUnusedKeys() {
            return _dataManager.GetUnusedKeys();
        }

        public IEnumerable<string> GetJsonKeys() {
            return _dataManager.GetJsonKeys();
        }
    }
}
