using System;
using System.Windows;
using Valg.EVA.Skanning.ContainerExtensions;
using Valg.EVA.Skanning.UserInterfaceElements;
using Valg.EVA.Skanning.UserInterfaceElements.ApplicationEvents;
using Valg.EVA.Skanning.UserInterfaceElements.Help;
using Valg.EVA.Skanning.UserInterfaceElements.LightBox;
using Valg.EVA.Skanning.UserInterfaceElements.Login;
using Valg.EVA.Skanning.UserInterfaceElements.TopBar;
using Valg.EVA.Skanning.UserInterfaceElements.MessageBox;
using Valg.EVA.Skanning.Identity;
using System.Windows.Input;
using Prism.Commands;
using Prism.Events;
using Valg.EVA.Skanning.Contracts.Security;
using Valg.EVA.Skanning.UserInterfaceElements.ApplicationTermination;
using Valg.EVA.Skanning.UserInterfaceElements.Language;
using Valg.EVA.Skanning.Verify.Startup.BoxComplete;
using Valg.EVA.Skanning.Verify.Startup.StartPage;
using Valg.EVA.Skanning.Verify.Startup.VerifyBallotPaper;
using Valg.EVA.Skanning.Verify.Startup.VerifyBallotPaper.Messaging.Commands;
using Valg.EVA.Skanning.Verify.Startup.VerifyBallotPaper.Messaging.Events;

namespace Valg.EVA.Skanning.Verify.Startup.VerifyWindow
{
    public class VerifyWindowViewModel : ViewModelBase, IVerifyWindowViewModel
    {
        private const int StartPageIndex = 0;
        private const int VerifyPageIndex = 1;
        private const int BoxCompletePageIndex = 2;
        private const int ChangeRolePageIndex = 3;
        private readonly ITypedFactory typedFactory;
        private readonly IIdentityProvider identityProvider;
        private readonly IWaitCursorProvider waitCursorProvider;
        private readonly string windowIcon = "/Valg.EVA.Skanning.Assets;component/Images/Icons/EvaVerify.ico";

        private int currentMainViewIndex;

        public VerifyWindowViewModel(ITypedFactory typedFactory,
            IEventAggregator eventAggregator, VerifyStartPageViewModel startPageViewModel,
            VerificationOverviewViewModel ballotPaperContainerViewModel, 
            IBoxCompleteViewModel boxCompleteViewModel, 
            LightBoxViewModel lightBoxViewModel, 
            IIdentityProvider identityProvider,
            IWaitCursorProvider waitCursorProvider)
        {
            this.typedFactory = typedFactory;
            StartPageViewModel = startPageViewModel;
            BallotPaperContainerViewModel = ballotPaperContainerViewModel;
            BoxCompleteViewModel = boxCompleteViewModel;
            LightBoxViewModel = lightBoxViewModel;
            this.identityProvider = identityProvider;
            this.waitCursorProvider = waitCursorProvider;

            GiveMainControlsFirstItemFocus = new DelegateCommand(SetMainControlsFirstItemFocus);
            GiveMainControlsLastItemFocus = new DelegateCommand(SetMainControlsLastItemFocus);

            RefreshCommand = new DelegateCommand(RequestDataRefresh);
            ShowHelpCommand = new DelegateCommand(eventAggregator.ShowHelpWindow);
        }

        public ICommand GiveMainControlsFirstItemFocus { get; set; }

        public ICommand GiveMainControlsLastItemFocus { get; set; }

        public ICommand RefreshCommand { get; private set; }

        public ICommand ShowHelpCommand { get; private set; }

        public VerifyStartPageViewModel StartPageViewModel { get; }

        public LightBoxViewModel LightBoxViewModel { get; }

        public int CurrentMainViewIndex
        {
            get { return currentMainViewIndex; }
            set
            {
                currentMainViewIndex = value;
                OnPropertyChanged();
                OnPropertyChanged(PropertyHelper.GetName<VerifyWindowViewModel>(vm => vm.IsFooterVisible));
            }
        }

        public VerificationOverviewViewModel BallotPaperContainerViewModel { get; }

        public IBoxCompleteViewModel BoxCompleteViewModel { get; }

        public bool IsFooterVisible
        {
            get
            {
                switch (currentMainViewIndex)
                {
                    case StartPageIndex:
                    case BoxCompletePageIndex:
                    case ChangeRolePageIndex:
                        return true;

                    case VerifyPageIndex:
                    default:
                        return false;
                }
            }
        }

        public void Login()
        {
            var loginProcess = typedFactory.Create<LoginProcessViewModel>();
            var loginResult = loginProcess.Login(ClaimDefinitions.VerifyAccessClaimType, windowIcon);

            if (loginResult != LoginResult.AccessGranted)
            {
                CloseApplication();
            }
            else
            {
                if (identityProvider.CurrentSelectedRole == null)
                {
                    ShowChangeRolePage(EventArgs.Empty);
                }
                else
                {
                    ShowStartPage(EventArgs.Empty);
                }
            }
        }

        protected override void SubscribeToViewModelSpecificEvents()
        {
            SubscribeToEvent<VerifyOnBoxIsStartedEvent, bool>(b =>
            {
                CurrentMainViewIndex = VerifyPageIndex;
                ChangeVisibilityOfBoxCountingInformationView(true);
            });
            SubscribeToEvent<BoxVerificationCompletedEvent, EventArgs>(args =>
            {
                CurrentMainViewIndex = BoxCompletePageIndex;
                ChangeVisibilityOfBoxCountingInformationView(false);
            });
            SubscribeToEvent<VerifyPreviousVerifiedBallotPaperEvent, EventArgs>(VerifyPreviousBallotPaper);
            SubscribeToEvent<ChangeRolePageRequestedEvent, EventArgs>(ShowChangeRolePage);
            SubscribeToEvent<MainWindowRequestedEvent, EventArgs>(ShowStartPage);
            SubscribeToEvent<LanguageChangedEvent, LanguageChangedEventArgs>(NotifyLanguageChanged);
        }

        private void NotifyLanguageChanged(LanguageChangedEventArgs obj)
        {
            RequestDataRefresh();
        }

        private void RequestDataRefresh()
        {
            if (CurrentMainViewIndex == StartPageIndex)
            {
                using (waitCursorProvider.GetWaitCursor())
                {
                    StartPageViewModel.RefreshData();
                }
            }
        }

        private void ChangeVisibilityOfBoxCountingInformationView(bool show)
        {
            PublishEvent<BoxCountingInformationViewChangeVisibilityEvent, BoxCountingInformationViewChangeVisibilityEventArgs>(new BoxCountingInformationViewChangeVisibilityEventArgs(show));
        }

        private void ShowStartPage(EventArgs eventArgs)
        {
            PublishEvent<BallotAbandonedEvent, EventArgs>(EventArgs.Empty);

            ChangeVisibilityOfBoxCountingInformationView(false);
            CurrentMainViewIndex = StartPageIndex;

            using (waitCursorProvider.GetWaitCursor())
            {
                StartPageViewModel.RefreshData();
            }
        }

        private void VerifyPreviousBallotPaper(EventArgs eventArgs)
        {
            BallotPaperContainerViewModel.NavigateBallotsViewModel.AdvanceToLastVerifiedBallotPaper();
        }

        private void SetMainControlsFirstItemFocus()
        {
            ActiveMainControlManager.SetFirstElementActive();
        }

        private void SetMainControlsLastItemFocus()
        {
            ActiveMainControlManager.SetLastElementActive();
        }

        private void ShowChangeRolePage(EventArgs eventArgs)
        {
            CurrentMainViewIndex = ChangeRolePageIndex;
        }

        public void CloseApplication()
        {
            PublishEvent<ApplicationTerminateRequestedEvent, EventArgs>(EventArgs.Empty);
        }

        public void ShowElectionConfigMissingWindow()
        {
            var resultDialog = typedFactory.Create<IMessageBox>();

            resultDialog.Initialize(Resources.Language.VerifyLanguageString.ElectionConfigMissingTextPart1,
                string.Empty, Resources.Language.VerifyLanguageString.ElectionConfigMissingTextPart2, MessageBoxType.Warning, null, new DelegateCommand(CloseApplication));

            var eventArgs = new LightBoxEventArgs(resultDialog as Window);
            PublishEvent<ShowLightBoxEvent, LightBoxEventArgs>(eventArgs);
        }
    }
}
