using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Runtime.CompilerServices;
using AudioApp.Annotations;

namespace AudioApp.ViewModel
{
    public abstract class ModelBase : INotifyPropertyChanged, INotifyPropertyChanging
    {
        public event PropertyChangedEventHandler PropertyChanged;
        public event PropertyChangingEventHandler PropertyChanging;

        [NotifyPropertyChangedInvocator]
        protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null) => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));

        protected virtual void OnPropertyChanging([CallerMemberName] string propertyName = null) => PropertyChanging?.Invoke(this, new PropertyChangingEventArgs(propertyName));

        protected readonly object syncRoot = new object();

        [NotifyPropertyChangedInvocator]
        protected virtual void OnPropertyChanged<T>(ref T field, T value, IEqualityComparer<T> comparer = null, [CallerMemberName] string propertyName = null)
        {
            lock (syncRoot)
            {
                // If the value is unchanged, do nothing.
                if (field.EqualsDefault(value, comparer)) return;

                try
                {
                    // Raise the "PropertyChanging" event.
                    PropertyChanging?.Invoke(this, new PropertyChangingEventArgs(propertyName));
                }
                finally
                {
                    // Set the value.
                    field = value;

                    // Raise the "PropertyChanged" event.
                    PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
                }
            }
        }
    }
}