using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading.Tasks;

namespace HashCalculator.GUI
{
    internal abstract class NotifyPropertyChanged : INotifyPropertyChanged
    {
        #region INotifyPropertyChanged
        public event PropertyChangedEventHandler? PropertyChanged;

        protected void Notify(string name)
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
        }

        protected void SetField<X>(ref X field, X value, [CallerMemberName] string? propertyName = null)
        {
            if (propertyName == null)
            {
                throw new InvalidOperationException();
            }

            if (EqualityComparer<X>.Default.Equals(field, value))
            {
                return;
            }

            field = value;

            Notify(propertyName);
        }
        #endregion
    }

    internal class ViewModel : NotifyPropertyChanged
    {
        public InputBarViewModel MainInput { get; } = new InputBarViewModel();
        public InputBarViewModel BigEntryInput { get; } = new InputBarViewModel();
        public InputBarViewModel AssetIdInput { get; } = new InputBarViewModel();
        public Model Model { get; }

        public ViewModel()
        {
            Model = new Model(this);
        }
    }

    internal class InputBarViewModel : NotifyPropertyChanged
    {
        private IEnumerable<InputEntry>? _items;
        public IEnumerable<InputEntry>? Items
        {
            get => _items;
            set => SetField(ref _items, value);
        }

        private InputEntry? selectedItem;
        public InputEntry? SelectedItem
        {
            get { return selectedItem; }
            set { SetField(ref selectedItem, value); }
        }

        private string? selectedValue;
        public string? SelectedValue
        {
            get { return selectedValue; }
            set { SetField(ref selectedValue, value); }
        }

        private string? _text;
        public string? Text
        {
            get { return _text; }
            set { SetField(ref _text, value); }
        }
    }
}