using System;
using System.Collections.Generic;
namespace Game
{
    /// 
    /// 数据绑定,改变数据时回调,只支持基本数据类型、list
    /// 
    public interface IMetaData
    {
        void AddEvent(Delegate callback);
        void RemoveEvent(Delegate callback);
    }
    public delegate void EventMetaData(ValueType valuePre, ValueType valueNow);
    public class MetaBase : IMetaData
    {
        protected T ValueReal;
        public T Value
        {
            get => ValueReal;
            set
            {
                if (ValueReal != null && ValueReal.Equals(value)) return;
                OnValueChange(ValueReal, value);
                ValueReal = value;
            }
        }
        private Delegate _handler;
        public void AddEvent(Delegate callback)
        {
            if (_handler == null)
            {
                _handler = callback;
            }
            else
            {
                _handler = (EventMetaData)_handler + (EventMetaData)callback;
            }
            //绑定的时候执行一次
            ((EventMetaData)callback)(ValueReal, ValueReal);
        }
        public void RemoveEvent(Delegate callback)
        {
            _handler = (EventMetaData)_handler - (EventMetaData)callback;
        }
        private void OnValueChange(T valuePre, T valueNow)
        {
            if (_handler == null)
            {
                return;
            }
            foreach (var callback in _handler.GetInvocationList())
            {
                ((EventMetaData)callback)(valuePre, valueNow);
            }
        }
        protected void OnValueChange()
        {
            OnValueChange(ValueReal, ValueReal);
        }
    }
    public class MetaData : MetaBase
    {
    }
    public class MetaList : MetaBase>
    {
        public T this[int key]
        {
            set => Value[key] = value;
            get => Value[key];
        }
        public void Add(T data)
        {
            ValueReal.Add(data);
            OnValueChange();
        }
        public void AddRange(IEnumerable collection)
        {
            ValueReal.AddRange(collection);
            OnValueChange();
        }
        public void Clear()
        {
            ValueReal.Clear();
            OnValueChange();
        }
        public void Remove(T data)
        {
            ValueReal.Remove(data);
            OnValueChange();
        }
    }
    public class MetaDictionary : MetaBase>
    {
        public MetaDictionary()
        {
            ValueReal = new Dictionary();
        }
        public TValue this[TKey key]
        {
            set
            {
                var isChange = !ValueReal.ContainsKey(key);
                ValueReal[key] = value;
                if (isChange)
                {
                    OnValueChange();
                }
            }
            get => ValueReal[key];
        }
        public int Count => ValueReal.Count;
        public void Clear()
        {
            ValueReal.Clear();
            OnValueChange();
        }
        public void Remove(TKey data)
        {
            ValueReal.Remove(data);
            OnValueChange();
        }
        public bool ContainsKey(TKey data)
        {
            return ValueReal.ContainsKey(data);
        }
        public Dictionary.Enumerator GetEnumerator()
        {
            return ValueReal.GetEnumerator();
        }
    }
}