using System;
using System.Collections.Generic;
using System.Runtime.CompilerServices;
using Valg.EVA.Skanning.Identity;
using Valg.EVA.Skanning.Resources;
using Valg.EVA.Skanning.Resources.Language;
using Valg.EVA.Skanning.UserInterfaceElements.Language;
using Prism.Events;
using ReactiveUI;
using Valg.EVA.Skanning.UserInterfaceElements;
using Valg.EVA.Skanning.UserInterfaceElements.Annotations;

namespace Valg.EVA.Skanning.JobManagement.Startup.UI
{
    public class ReactiveViewModel : ReactiveObject, IViewModelBase
    {

        private readonly List<KeyValuePair<EventBase, SubscriptionToken>> eventsAndSubscriptionTokens = new List<KeyValuePair<EventBase, SubscriptionToken>>();
        private IEventAggregator eventAggregator;

        public LanguageString LanguageString => LanguageResource.LanguageString;

        public ScanLanguageString ScanLanguageString => LanguageResource.ScanLanguageString;

        public VerifyLanguageString VerifyLanguageString => LanguageResource.VerifyLanguageString;

        public JobManagementLanguageString JobManagementLanguageString => LanguageResource.JobManagementLanguageString;

        private void NotifySecurityContextHasChanged(EventArgs eventArgs)
        {
            
            
            OnPropertyChanged(null);
        }

        public void SetupEventSubscriptions(IEventAggregator eventAgg)
        {
            if (eventAggregator != null)
            {
                throw new InvalidOperationException("EventAggregator in viewModel is already set.");
            }

            eventAggregator = eventAgg;

            SubscribeToEvent<LanguageChangedEvent, LanguageChangedEventArgs>(NotifyLanguageChanged);
            SubscribeToEvent<SecurityContextHasChangedEvent, EventArgs>(NotifySecurityContextHasChanged);

            SubscribeToViewModelSpecificEvents();
        }

        private void NotifyLanguageChanged(LanguageChangedEventArgs obj)
        {
            OnPropertyChanged(null);
        }

        protected virtual void SubscribeToViewModelSpecificEvents()
        {

        }

        protected void SubscribeToEvent<EventType, ArgsType>(Action<ArgsType> action) where EventType : PubSubEvent<ArgsType>, new()
        {
            var eventType = eventAggregator.GetEvent<EventType>();
            var token = eventType.Subscribe(action);
            eventsAndSubscriptionTokens.Add(new KeyValuePair<EventBase, SubscriptionToken>(eventType, token));
        }

        protected void PublishEvent<EventType, ArgsType>(ArgsType action) where EventType : PubSubEvent<ArgsType>, new()
        {
            var eventType = eventAggregator.GetEvent<EventType>();
            eventType.Publish(action);
        }

        [NotifyPropertyChangedInvocator]
        protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
        {
            this.RaisePropertyChanged(propertyName);
        }

        public void Dispose()
        {
            foreach (var keyValuePair in eventsAndSubscriptionTokens)
            {
                var eventBase = keyValuePair.Key;
                var token = keyValuePair.Value;
                eventBase.Unsubscribe(token);
            }
        }
    }
}
