using Cryville.Common.ComponentModel;
using System.Reflection;
using UnityEngine;
using UnityEngine.UI;
using RangeAttribute = Cryville.Common.ComponentModel.RangeAttribute;

namespace Cryville.Crtr.Browsing {
	public class PropertyPanel : MonoBehaviour {
		[SerializeField]
		GameObject m_bool;
		[SerializeField]
		GameObject m_number;

		PropertyInfo _property;
		object _target;

		Text _key;
		Transform _valueContainer;
		PropertyValuePanel _value;

#pragma warning disable IDE0051
		void Awake() {
			_key = transform.Find("Key").GetComponent<Text>();
			_valueContainer = transform.Find("Value");
		}
#pragma warning restore IDE0051
		public void Load(PropertyInfo prop, object target) {
			_target = target;
			_property = prop;
			_key.text = prop.Name;

			GameObject vp;
			if (prop.PropertyType == typeof(bool)) vp = m_bool;
			else if (prop.PropertyType == typeof(float) || prop.PropertyType == typeof(int)) vp = m_number;
			else return;
			_value = GameObject.Instantiate(vp, _valueContainer, false).GetComponent<PropertyValuePanel>();
			if (_value is PVPNumber) {
				var t = (PVPNumber)_value;
				t.IntegerMode = prop.PropertyType == typeof(int);
				var attr = prop.GetCustomAttributes(typeof(RangeAttribute), true);
				if (attr.Length > 0) {
					var u = (RangeAttribute)attr[0];
					t.Range = new Vector2(u.Min, u.Max);
				}
				attr = prop.GetCustomAttributes(typeof(PrecisionAttribute), true);
				if (attr.Length > 0) {
					var u = (PrecisionAttribute)attr[0];
					t.Precision = u.Precision;
				}
				attr = prop.GetCustomAttributes(typeof(StepAttribute), true);
				if (attr.Length > 0) {
					var u = (StepAttribute)attr[0];
					t.MaxStep = u.Step;
				}
				attr = prop.GetCustomAttributes(typeof(LogarithmicScaleAttribute), true);
				if (attr.Length > 0) {
					t.LogarithmicMode = true;
				}
			}
			_value.Callback = SetValueToObject;
			GetValueFromObject();
		}

		void GetValueFromObject() {
			_value.Value = _property.GetValue(_target, null);
		}

		void SetValueToObject(object value) {
			_property.SetValue(_target, value, null);
			GetValueFromObject();
		}
	}
}