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

namespace ImageCatalog_2
{
    public class ViewModelBase : INotifyPropertyChanged
    {
        private readonly SynchronizationContext? _synchronizationContext;
        private Control? _control;

        protected ViewModelBase()
        {
            // Capture the synchronization context (UI thread context)
            _synchronizationContext = SynchronizationContext.Current;
        }

        /// <summary>
        /// Set a Control to use for thread marshalling in WinForms applications.
        /// This is required for proper cross-thread handling with data binding.
        /// </summary>
        public void SetControl(Control control)
        {
            _control = control;
        }

        public event PropertyChangedEventHandler? PropertyChanged;
        
        // This method is called by the Set accessor of each property.
        // The CallerMemberName attribute that is applied to the optional propertyName
        // parameter causes the property name of the caller to be substituted as an argument.
        protected void NotifyPropertyChanged([CallerMemberName] String propertyName = "")
        {
            if (PropertyChanged == null)
                return;

            // If we have a Control reference (WinForms), use Control.Invoke for proper marshalling
            if (_control != null)
            {
                if (_control.InvokeRequired)
                {
                    _control.Invoke(() => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)));
                }
                else
                {
                    PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
                }
            }
            // Fallback to SynchronizationContext if available
            else if (_synchronizationContext != null && SynchronizationContext.Current != _synchronizationContext)
            {
                // We're on a different thread, marshal to the UI thread
                _synchronizationContext.Send(_ =>
                {
                    PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
                }, null);
            }
            else
            {
                // We're already on the UI thread or no sync context available
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }
        }

    }
}
