using System;
using Valg.EVA.Skanning.Identity;
using Valg.EVA.Skanning.UserInterfaceElements;
using Valg.EVA.Skanning.UserInterfaceElements.ApplicationEvents;
using Valg.EVA.Skanning.UserInterfaceElements.TopBar;
using Valg.EVA.Skanning.Verify.Startup.BoxIsLocked;
using Valg.EVA.Skanning.Verify.Startup.NavigationTip;
using Valg.EVA.Skanning.Verify.Startup.VerifyBallotPaper.Messaging.Commands;
using Valg.EVA.Skanning.Verify.Startup.VerifyBallotPaper.ReadModel;

namespace Valg.EVA.Skanning.Verify.Startup.VerifyBallotPaper
{
    public class VerificationOverviewViewModel : ViewModelBase
    {
        private readonly IIdentityProvider identityProvider;
        private readonly IVerificationProcessErrorsAndWarnings verificationProcessErrorsAndWarnings;
        private readonly IWaitCursorProvider waitCursorProvider;
        private readonly INavigationTipViewModel navigationTipViewModel;
        private readonly IReadModelHub readModelHub;

        public VerificationOverviewViewModel(INavigationTipViewModel navigationTipViewModel, 
            INavigateBallotsViewModel navigateBallotsViewModel, 
            IReadModelHub readModelHub, 
            IIdentityProvider identityProvider, 
            IVerificationProcessErrorsAndWarnings verificationProcessErrorsAndWarnings,
            IWaitCursorProvider waitCursorProvider)
        {
            NavigateBallotsViewModel = navigateBallotsViewModel;
            this.identityProvider = identityProvider;
            this.verificationProcessErrorsAndWarnings = verificationProcessErrorsAndWarnings;
            this.waitCursorProvider = waitCursorProvider;
            this.navigationTipViewModel = navigationTipViewModel;
            this.readModelHub = readModelHub;

            navigateBallotsViewModel.PropertyChanged += ((s, e) => OnPropertyChanged(null));
        }

        protected override void SubscribeToViewModelSpecificEvents()
        {
            SubscribeToEvent<BoxIsSelectedForVerifyEvent, BoxEventArgs>(StartVerification);
            SubscribeToEvent<BoxIsSelectedForReviewEvent, BoxEventArgs>(StartReviewOfVerification);
            SubscribeToEvent<VerificationResolvedOnVerifiableViewModelEvent, VerificationWasResolvedEventArgs>(RefreshViewWhenFieldActionCommittedSomewhere);
        }

        private void RefreshViewWhenFieldActionCommittedSomewhere(VerificationWasResolvedEventArgs obj)
        {
            OnPropertyChanged(null);
        }
        
        public INavigateBallotsViewModel NavigateBallotsViewModel { get; }

        private void PublishVerifyOnBoxIsStarted()
        {
            PublishEvent<VerifyOnBoxIsStartedEvent, bool>(true);
        }

        private void PublishSetDataOnBoxCountingInformationView(BoxEventArgs args)
        {
            var originatingLocation = args.OriginatingLocation;
            var hasNoPollingDistrictInformation = string.IsNullOrEmpty(originatingLocation);
            if (hasNoPollingDistrictInformation)
            {
                originatingLocation = identityProvider.CurrentSelectedArea.AreaName; 
            }
            else if (args.Counting.IsCurrentlyCountedByTopLevelCountingAuthority())
            {
                
                originatingLocation = $"{identityProvider.CurrentSelectedArea.AreaName} | {originatingLocation}";
            }

            var eventArgs = new BoxCountingInformationViewSetDataEventArgs(args.VotingCategoryName, args.BoxNumber, originatingLocation, args.Counting.CountingType, args.Counting.CountNumber);
            PublishEvent<BoxCountingInformationViewSetDataEvent, BoxCountingInformationViewSetDataEventArgs>(eventArgs);
        }

        private void StartVerification(BoxEventArgs args)
        {
            if (readModelHub.IsBoxStillOpenForVerification(args.BoxCountingId))
            {
                navigationTipViewModel.ShowTipIfNotHiddenByUser();

                using (waitCursorProvider.GetWaitCursor())
                {
                    NavigateBallotsViewModel.Reset(args.BoxCountingId);

                    PublishSetDataOnBoxCountingInformationView(args);

                    PublishVerifyOnBoxIsStarted();

                    NavigateBallotsViewModel.AdvanceToNextBallotPaper();

                    OnPropertyChanged(null);
                }
            }
            else
            {
                verificationProcessErrorsAndWarnings.ShowBoxIsLockedOrDeletedInformation();
                GoToStartVerifyPage();
            }
        }

        private void StartReviewOfVerification(BoxEventArgs args)
        {
            using (waitCursorProvider.GetWaitCursor())
            {
                if (readModelHub.IsBoxStillOpenForVerification(args.BoxCountingId))
                {
                    NavigateBallotsViewModel.Reset(args.BoxCountingId);

                    PublishSetDataOnBoxCountingInformationView(args);

                    NavigateBallotsViewModel.Preload(readModelHub.GetBallotIdsVerified(args.BoxCountingId));

                    PublishVerifyOnBoxIsStarted();

                    NavigateBallotsViewModel.AdvanceToNextBallotPaper();

                    OnPropertyChanged(null);
                }
                else
                {
                    verificationProcessErrorsAndWarnings.ShowBoxIsLockedOrDeletedInformation();
                    GoToStartVerifyPage();
                }
            }
        }

        private void GoToStartVerifyPage()
        {
            PublishEvent<MainWindowRequestedEvent, EventArgs>(EventArgs.Empty);
        }
    }
}
