using Cryville.Common.Unity;
using Cryville.Common.Unity.Input;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

namespace Cryville.Crtr.Config {
	public class InputConfigPanel : MonoBehaviour {
		[SerializeField]
		ConfigScene m_configScene;

		[SerializeField]
		GameObject m_inputDialog;

		[SerializeField]
		Transform m_deviceList;

		[SerializeField]
		GameObject m_prefabListItem;

		[SerializeField]
		Transform m_entryList;

		[SerializeField]
		GameObject m_prefabInputConfigEntry;

		public InputProxy proxy;
		readonly Dictionary<string, InputConfigPanelEntry> _entries = new Dictionary<string, InputConfigPanelEntry>();

		string _sel;
		public void OpenDialog(string entry) {
			_sel = entry;
			m_inputDialog.SetActive(true);
			CallHelper.Purge(m_deviceList);
			Game.InputManager.EnumerateEvents(ev => { });
			_recvsrcs.Clear();
			AddSourceItem(null);
		}

		public void CloseDialog() {
			m_inputDialog.SetActive(false);
		}

		public void CloseDialog(InputSource? src) {
			proxy.Set(new InputProxyEntry {
				Target = _sel,
				Source = src,
			});
			m_inputDialog.SetActive(false);
		}

		void Start() {
			foreach (var i in m_configScene.ruleset.Root.inputs) {
				var e = GameObject.Instantiate(m_prefabInputConfigEntry, m_entryList.transform).GetComponent<InputConfigPanelEntry>();
				_entries.Add(i.Key, e);
				e.SetKey(this, i.Key);
				OnProxyChanged(this, proxy[i.Key]);
			}
			proxy.ProxyChanged += OnProxyChanged;
		}

		void OnProxyChanged(object sender, ProxyChangedEventArgs e) {
			_entries[e.Name].SetEnabled(!e.Used);
			_entries[e.Name].SetValue(e.Proxy == null ? "None" : e.Proxy.Value.Handler.GetTypeName(e.Proxy.Value.Type));
		}

		readonly List<InputSource?> _recvsrcs = new List<InputSource?>();
		void Update() {
			if (m_inputDialog.activeSelf) {
				Game.InputManager.EnumerateEvents(ev => {
					AddSourceItem(ev.Id.Source);
				});
			}
		}

		void AddSourceItem(InputSource? src) {
			if (_recvsrcs.Contains(src)) return;
			_recvsrcs.Add(src);
			var obj = Instantiate(m_prefabListItem, m_deviceList);
			obj.transform.Find("Text").GetComponent<Text>().text = src == null ? "None" : src.Value.Handler.GetTypeName(src.Value.Type);
			var btn = obj.GetComponent<Button>();
			if (src != null) btn.interactable = !proxy.IsUsed(src.Value);
			btn.onClick.AddListener(() => {
				CloseDialog(src);
			});
		}
	}
}
