using EventBus;
using FPGACoder.Model;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading.Tasks;

namespace FPGACoder.ViewModel
{
    public abstract class ViewModelBase<TModel> : IViewModelBase where TModel : IModel
    {
        public ViewModelBase()
        {
            if (typeof(TModel).IsAnsiClass && !typeof(TModel).IsAbstract)
            {
                Model = Activator.CreateInstance<TModel>();
            }
        }
        public virtual void UpDateModel(TModel model)
        {
            Model = model;
            RefreshUI();
        }
        public virtual void Init()
        {

        }
        [AllowNull]
        private TModel model = default;
        private bool disposedValue;

        [AllowNull]
        public virtual TModel Model { get => model; set => UpdateProperty(ref model, value); }
        IModel IViewModelBase.Model => model;

        protected void RefreshUI()
        {
            GetType().GetProperties(System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Instance).ToList().ForEach(x =>
            {
                OnPropertyChanged(x.Name);
            });
        }
        #region 接口实现
        public event PropertyChangedEventHandler? PropertyChanged;
        protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = "")
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }

        public void UpdateProperty<T>(ref T properValue, T newValue, [CallerMemberName] string propertyName = "")
        {
            if (Equals(properValue, newValue))
            {
                return;
            }
            properValue = newValue;

            OnPropertyChanged(propertyName);
        }

        public void UpdateProperty<T>(TypedReference properValue, T newValue, [CallerMemberName] string propertyName = "")
        {
            if (Equals(__refvalue(properValue, T), newValue))
            {
                return;
            }
            __refvalue(properValue, T) = newValue;

            OnPropertyChanged(propertyName);
        }
        #endregion

        [return: NotNull]
        protected IEventData<TData> GetEvent<TData>() => EventBroker.Instance.GetEvent<TData>();

        [return: NotNull]
        protected IEventData<TData, T> GetEvent<TData, T>() => EventBroker.Instance.GetEvent<TData, T>();

        [return: NotNull]
        public IAnonymousEventData GetEvent([NotNull] string eventName) => EventBroker.Instance.GetEvent(eventName);

        [return: NotNull]
        public IAnonymousEventData<T> GetEvent<T>([NotNull] string eventName) => EventBroker.Instance.GetEvent<T>(eventName);

        protected virtual void DisposeManaged()
        {
        }
        protected virtual void DisposeUnmanaged()
        {

        }
        protected virtual void Dispose(bool disposing)
        {
            if (!disposedValue)
            {
                if (disposing)
                {
                    DisposeManaged();
                    // TODO: 释放托管状态(托管对象)
                }
                DisposeUnmanaged();
                // TODO: 释放未托管的资源(未托管的对象)并重写终结器
                // TODO: 将大型字段设置为 null
                disposedValue = true;
            }
        }

        // // TODO: 仅当“Dispose(bool disposing)”拥有用于释放未托管资源的代码时才替代终结器
        // ~NotifyPropertyChanged()
        // {
        //     // 不要更改此代码。请将清理代码放入“Dispose(bool disposing)”方法中
        //     Dispose(disposing: false);
        // }

        public void Dispose()
        {
            // 不要更改此代码。请将清理代码放入“Dispose(bool disposing)”方法中
            Dispose(disposing: true);
            GC.SuppressFinalize(this);
        }
    }
}
