using System.Collections.ObjectModel;
using Valg.EVA.Skanning.UserInterfaceElements.Commands;
using System.Linq;
using System.Windows.Input;
using Valg.EVA.Skanning.UserInterfaceElements;
using Valg.EVA.Skanning.Verify.Startup.VerifyBallotPaper.Messaging.Commands;
using Valg.EVA.Skanning.Verify.Startup.VerifyBallotPaper.Messaging.Events;
using Valg.EVA.Skanning.Verify.Startup.VerifyBallotPaper.WriteModel;

namespace Valg.EVA.Skanning.Verify.Startup.VerifyBallotPaper.PageXOfY
{
    public class PageXOfYViewModel : ViewModelBase, IPageXOfYViewModel
    {
        private readonly IWriteModelHub writeModelHub;
        private readonly RelayCommand advancePreviousCommand;
        private readonly RelayCommand advanceNextCommand;
        private int currentPage;
        private int totalNumberOfPages;

        public PageXOfYViewModel(IWriteModelHub writeModelHub)
        {
            this.writeModelHub = writeModelHub;
            
            advancePreviousCommand = new RelayCommand(s => AdvancePage(false));
            advanceNextCommand = new RelayCommand(s => AdvancePage(true));

            PageXOfYNavigationTooltips = new ObservableCollection<PageXOfYNavigationTooltip>();
        }

        public void ChangePageIndexToCurrentRejectionIfSet()
        {
            if (writeModelHub.PageIndexRejectedOn.HasValue)
            {
                CurrentPage = writeModelHub.PageIndexRejectedOn.Value + 1;
            }
        }

        public void AddPageNavigationTooltip(PageXOfYNavigationTooltip tooltip)
        {
            PageXOfYNavigationTooltips.Add(tooltip);
        }

        public string PageCounterText => string.Format(Resources.Language.VerifyLanguageString.PageCounterTemplate, CurrentPage, TotalNumberOfPages);

        public int CurrentPage
        {
            get { return currentPage; }
            set
            {
                if (currentPage != value)
                {
                    currentPage = value;
                    RaisePageChangedEvent();
                    
                    
                    OnPropertyChanged(null);
                }
            }
        }

        public int TotalNumberOfPages
        {
            get { return totalNumberOfPages; }
            private set
            {
                totalNumberOfPages = value;
                OnPropertyChanged(null);
            }
        }

        public int CurrentPageIndex => CurrentPage - 1;

        public ICommand AdvanceToPreviousPage => advancePreviousCommand;

        public ICommand AdvanceToNextPage => advanceNextCommand;

        public bool IsBackOnePageEnabled
        {
            get
            {
                if (IsBallotPaperRejected)
                {
                    return IsRejectedButCanNavigateBackward;
                }

                return CurrentPage > 1;
            }
        }
        private bool IsRejectedButCanNavigateBackward => (CurrentPage > 1 && CurrentPage <= writeModelHub.PageIndexRejectedOn + 1);

        public bool IsForwardOnePageEnabled
        {
            get
            {
                if (IsBallotPaperRejected)
                {
                    return IsRejectedButCanNavigateForward;
                }

                return CurrentPage != TotalNumberOfPages;
            }
        }
        private bool IsRejectedButCanNavigateForward => CurrentPage < writeModelHub.PageIndexRejectedOn + 1;

        public string AdvanceToNextPageTooltip => GetTooltip(1);

        public string AdvanceToPreviousPageTooltip => GetTooltip(-1);

        public ObservableCollection<PageXOfYNavigationTooltip> PageXOfYNavigationTooltips { get; }

        public bool IsBallotPaperRejected => writeModelHub.IsRejected;

        public void SetFirstOrCurrentPage()
        {
            if (CurrentPage == 0)
                CurrentPage = 1;
        }

        protected override void SubscribeToViewModelSpecificEvents()
        {
            SubscribeToEvent<FocusRequestedByVerifiableViewModelVisitationEvent, FocusRequestedByVerifiableViewModelVisitationEventArgs>(e => CurrentPage = e.ViewModelThatRequestedFocus.PageIndex + 1);
            SubscribeToEvent<PagesCollectionChangedEvent, PagesCollectionChangedEventArgs>(PagesCollectionChanged);
        }

        private void PagesCollectionChanged(PagesCollectionChangedEventArgs pagesCollectionChangedEventArgs)
        {
            TotalNumberOfPages = pagesCollectionChangedEventArgs.NumberOfPages;
            OnPropertyChanged(null);
        }

        private void RaisePageChangedEvent()
        {
            PublishEvent<PageChangedEvent, PageChangedEventArgs>(new PageChangedEventArgs { NewPage = CurrentPage });
        }

        private void AdvancePage(bool forward)
        {
            int delta = 1;
            if (!forward)
            {
                delta = -1;
            }

            if (!IsBallotPaperRejected
                || (IsRejectedButCanNavigateForward && forward)
                || (IsRejectedButCanNavigateBackward && !forward))
            {
                var previewNewPage = CurrentPage + delta;
                if (previewNewPage >= 1 && previewNewPage <= TotalNumberOfPages)
                {
                    CurrentPage += delta;
                }
            }
        }

        private string GetTooltip(int delta)
        {
            var navigationTooltip = PageXOfYNavigationTooltips.FirstOrDefault(t => t.PageNumber == CurrentPage + delta);

            if (navigationTooltip != null)
            {
                return navigationTooltip.Tooltip;
            }

            return string.Empty;
        }
    }
}
