using System.Collections.Generic;
using System.Collections.ObjectModel;
using Valg.EVA.Skanning.ServicesModel.ServiceContracts.Verification.Read;
using Valg.EVA.Skanning.UserInterfaceElements.EventArgs;
using Valg.EVA.Skanning.UserInterfaceElements;
using Valg.EVA.Skanning.Verify.Startup.VerifyBallotPaper.Candidate;
using Valg.EVA.Skanning.Verify.Startup.VerifyBallotPaper.VerifiableViewModelsCollection;
using Valg.EVA.Skanning.Verify.Startup.VerifyBallotPaper.Messaging.Commands;
using Valg.EVA.Skanning.Verify.Startup.VerifyBallotPaper.WriteModel;

namespace Valg.EVA.Skanning.Verify.Startup.VerifyBallotPaper.RenumberStrikeout
{
    public class RenumberStrikeoutViewModel : ViewModelBase, IViewModelWithVerifiableContent
    {
        private readonly RenumberStrikeoutContextMenuCommand renumberStrikeoutContextMenuCommand;
        private readonly IWriteModelHub writeModelHub;
        private bool isContextMenuOpen;
        private bool needsVerification;
        private bool isActionButtonFocused;
        private bool neededVerification;
        private int? renumberAsGivenByCorrection;
        private bool? strikeoutAsGivenByCorrection;
        private RenumberStrikeoutReadOnly readOnlyModel;

        public RenumberStrikeoutViewModel(RenumberStrikeoutContextMenuCommand renumberStrikeoutContextMenuCommand, IWriteModelHub writeModelHub)
        {
            this.renumberStrikeoutContextMenuCommand = renumberStrikeoutContextMenuCommand;
            this.writeModelHub = writeModelHub;

            renumberStrikeoutContextMenuCommand.ContextMenuCommandWasExecuted += ContextMenuCommandWasExecuted;
        }

        public void SetModel(RenumberStrikeoutReadOnly renumberStrikeoutReadOnly)
        {
            readOnlyModel = renumberStrikeoutReadOnly;

            NeededVerification = readOnlyModel.NeededVerification;
            NeedsVerification = readOnlyModel.NeedsVerification;

            renumberAsGivenByCorrection = readOnlyModel.RenumberAsGivenByCorrection;
            strikeoutAsGivenByCorrection = readOnlyModel.StrikeoutAsGivenByCorrection;

            OnPropertyChanged(null);
        }

        public string Name { get; set; }

        public int CandidateRank { get; set; }

        public bool NeededVerification
        {
            get { return neededVerification; }
            set
            {
                neededVerification = value;
                OnPropertyChanged();
            }
        }

        public int VerificationOrder { get; set; }

        public int PageIndex { get; set; }

        public void RaiseRenumberSelectedEvent()
        {
            renumberStrikeoutContextMenuCommand.RaiseRenumberSelectedEvent(Renumber.Value);
        }

        public ObservableCollection<ContextMenuViewModel> VerifyCommand => renumberStrikeoutContextMenuCommand.CommandList;

        public string CandidateRankFormatted => $"{CandidateRank}.";

        public int? Renumber
        {
            get
            {
                if (strikeoutAsGivenByCorrection.GetValueOrDefault())
                {
                    return null;
                }


                int? renumber = null;
                if (renumberAsGivenByCorrection.HasValue)
                {
                    if (renumberAsGivenByCorrection != 0)
                    {
                        renumber = renumberAsGivenByCorrection.Value;
                    }
                }
                else
                {
                    if (readOnlyModel != null)
                    {
                        if ((!readOnlyModel.IsNoChange || NeedsVerification)
                            && readOnlyModel.RenumberAsInterpretedByScanner.HasValue)
                        {
                            renumber = readOnlyModel.RenumberAsInterpretedByScanner.Value;
                        }
                    }
                }

                return renumber;
            }
        }

        public void SetPossibleRenumberValues(List<int> possibleRenumberValues)
        {
            renumberStrikeoutContextMenuCommand.SetPossibleRenumberValues(possibleRenumberValues);
        }

        public bool HasCandidateBeenStrikedOut
        {
            get
            {
                var strikedOut = false;

                if (strikeoutAsGivenByCorrection.HasValue)
                {
                    strikedOut = strikeoutAsGivenByCorrection.Value;
                }
                else
                {
                    if (!renumberAsGivenByCorrection.HasValue && readOnlyModel != null)
                    {
                        if ((!readOnlyModel.IsNoChange || NeedsVerification)
                            && readOnlyModel.StrikeoutAsInterpretedByScanner.HasValue)
                        {
                            strikedOut = readOnlyModel.StrikeoutAsInterpretedByScanner.Value;
                        }
                    }
                }

                return strikedOut;
            }
        }

        public bool HasUserCorrectionsBeenMade => renumberAsGivenByCorrection.HasValue
                                                  || strikeoutAsGivenByCorrection.HasValue
                                                  || (!NeedsVerification && readOnlyModel != null && readOnlyModel.IsNoChange);

        public bool IsContextMenuOpen
        {
            get { return isContextMenuOpen; }
            set
            {
                if (isContextMenuOpen != value)
                {
                    isContextMenuOpen = value;
                    OnPropertyChanged();
                }
            }
        }

        public bool NeedsVerification
        {
            get
            {
                return needsVerification;
            }
            set
            {
                needsVerification = value;
                OnPropertyChanged();
            }
        }

        public bool IsActionButtonFocused
        {
            get { return isActionButtonFocused; }
            set
            {
                isActionButtonFocused = value;
                OnPropertyChanged();
            }
        }

        public void RemainFocusAtThisViewModel()
        {
            IsActionButtonFocused = true;
        }

        public void BringToFocus()
        {
            IsActionButtonFocused = true;
            IsContextMenuOpen = true;
        }

        public void Reset()
        {
            renumberAsGivenByCorrection = null;
            strikeoutAsGivenByCorrection = null;

            NeedsVerification = NeededVerification;
            
            OnPropertyChanged(null);
        }

        private void ContextMenuCommandWasExecuted(object sender, CustomEventArgs args)
        {
            var initiallyNeededVerification = NeedsVerification;

            int? renumberValue;
            bool? strikeoutValue;

            if (args.IntValue == 0)
            {
                renumberValue = null;
            }
            else
            {
                renumberValue = args.IntValue;
            }

            if (args.BoolValue == false)
            {
                strikeoutValue = null;
            }
            else
            {
                strikeoutValue = args.BoolValue;
            }

            renumberAsGivenByCorrection = args.IntValue;
            strikeoutAsGivenByCorrection = args.BoolValue;

            NeedsVerification = false;
            writeModelHub.AddRenumberStrikeoutModification(CandidateRank, renumberValue, strikeoutValue);

            IsContextMenuOpen = false;

            OnPropertyChanged(null);

            var renumberSelectedEventArgs = new RenumberSelectedEventArgs(renumberAsGivenByCorrection.Value);
            PublishEvent<RenumberSelectedEvent, RenumberSelectedEventArgs>(renumberSelectedEventArgs);

            var actionWasCommmitedArgs = new VerificationWasResolvedEventArgs(this, initiallyNeededVerification);
            PublishEvent<VerificationResolvedOnVerifiableViewModelEvent, VerificationWasResolvedEventArgs>(actionWasCommmitedArgs);
        }
    }
}

