using Cryville.Crtr.Ruleset;
using Cryville.Crtr.UI;
using Newtonsoft.Json;
using System;
using System.IO;
using System.Text;
using UnityEngine;
using Logger = Cryville.Common.Logging.Logger;

namespace Cryville.Crtr.Config.UI {
	public class ConfigPanelMaster : MonoBehaviour {
		[SerializeField]
		Menu m_menu;

		[SerializeField]
		Transform m_content;

		[SerializeField]
		PropertyMasterPanel m_genericConfigPanel;

		[SerializeField]
		PropertyMasterPanel m_rulesetConfigPanel;

		[SerializeField]
		InputConfigPanel m_inputConfigPanel;

		public RulesetDefinition ruleset;
		RulesetConfig _rscfg;

		bool _loaded;

		void OnEnable() {
			try {
				PdtEvaluator.Instance.Reset();
				FileInfo file = new FileInfo(
					Game.GameDataPath + "/rulesets/" + Settings.Default.LoadRuleset
				);
				if (!file.Exists) {
					throw new FileNotFoundException("Ruleset for the chart not found\nMake sure you have imported the ruleset");
				}
				DirectoryInfo dir = file.Directory;
				using (StreamReader reader = new StreamReader(file.FullName, Encoding.UTF8)) {
					ruleset = JsonConvert.DeserializeObject<RulesetDefinition>(reader.ReadToEnd(), new JsonSerializerSettings() {
						MissingMemberHandling = MissingMemberHandling.Error
					});
					if (ruleset.format != RulesetDefinition.CURRENT_FORMAT) throw new FormatException("Invalid ruleset file version");
					ruleset.LoadPdt(dir);
				}
				FileInfo cfgfile = new FileInfo(
					Game.GameDataPath + "/config/rulesets/" + Settings.Default.LoadRulesetConfig
				);
				if (!cfgfile.Exists) {
					if (!cfgfile.Directory.Exists) cfgfile.Directory.Create();
					_rscfg = new RulesetConfig();
				}
				else {
					using (StreamReader cfgreader = new StreamReader(cfgfile.FullName, Encoding.UTF8)) {
						_rscfg = JsonConvert.DeserializeObject<RulesetConfig>(cfgreader.ReadToEnd(), new JsonSerializerSettings() {
							MissingMemberHandling = MissingMemberHandling.Error
						});
					}
				}

				m_genericConfigPanel.Adapter = new DefaultPropertyMasterAdapter(_rscfg.generic);
				m_rulesetConfigPanel.Adapter = new RulesetConfigPropertyMasterAdapter(ruleset.Root.configs, _rscfg.configs);

				var proxy = new InputProxy(ruleset.Root, null, new Vector2(Screen.width, Screen.height));
				proxy.LoadFrom(_rscfg.inputs);
				m_inputConfigPanel.proxy = proxy;

				m_inputConfigPanel.OnConfigEnable();

				_loaded = true;
			}
			catch (Exception ex) {
				Popup.CreateException(ex);
				Logger.Log("main", 4, "Config", "An error occurred while loading the config: {0}", ex);
				m_menu.Back();
			}
		}

		public void SwitchCategory(GameObject cat) {
			foreach (Transform c in m_content) {
				c.gameObject.SetActive(false);
			}
			cat.SetActive(true);
		}

		void OnDisable() {
			if (_loaded) {
				_loaded = false;
				m_inputConfigPanel.proxy.SaveTo(_rscfg.inputs);
				m_inputConfigPanel.proxy.Dispose();
				FileInfo cfgfile = new FileInfo(
					Game.GameDataPath + "/config/rulesets/" + Settings.Default.LoadRulesetConfig
				);
				using (StreamWriter cfgwriter = new StreamWriter(cfgfile.FullName, false, Encoding.UTF8)) {
					cfgwriter.Write(JsonConvert.SerializeObject(_rscfg, Game.GlobalJsonSerializerSettings));
				}
				m_inputConfigPanel.OnConfigDisable();
			}
		}
	}
}
