using System;
using Valg.EVA.Skanning.ServicesModel.ServiceContracts.Verification.Read;
using Prism.Commands;
using Valg.EVA.Skanning.UserInterfaceElements;
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.WriteIns
{
    public class WriteInViewModel : ViewModelBase, IViewModelWithVerifiableContent
    {
        private readonly IWriteModelHub writeModelHub;

        private string currentValue;
        private string affiliationId;
        private string candidateName;
        private bool ignoreWriteIn;
        private bool? isWriteInFocused;
        private bool neededVerification;
        private bool needsVerification;
        private string originalValue;
        private WriteInReadOnly writeInReadOnlyModel;
        private WriteInSelectionItem selectedSearchItem;
        private bool isLoaded;

        public WriteInViewModel(IWriteModelHub writeModelHub)
        {
            this.writeModelHub = writeModelHub;
            WriteInSelectionFromDropDownCommand = new DelegateCommand(WriteInSelectionChanged);
            EnterKeyWasPressedOnIgnoreCheckboxCommand = new DelegateCommand(EnterKeyWasPressedOnIgnoreCheckbox);
        }

        public void SetModel(WriteInReadOnly writeInReadOnly, bool isReset)
        {
            writeInReadOnlyModel = writeInReadOnly;

            neededVerification = writeInReadOnlyModel.NeededVerification;
            NeedsVerification = writeInReadOnlyModel.NeedsVerification;

            IgnoreWriteIn = writeInReadOnlyModel.IgnoreWriteIn;

            affiliationId = writeInReadOnlyModel.AffiliationId;
            candidateName = writeInReadOnlyModel.CandidateName;

            isLoaded = true;

            if (isReset && writeInReadOnlyModel.NeededVerification)
            {
                Reset();
            }

            
            
            
            neededVerification = true;
        }

        public string CurrentValue
        {
            get
            {
                if (string.IsNullOrEmpty(currentValue))
                {
                    currentValue = writeInReadOnlyModel.ScannerValue;

                    if (SelectedSearchItem != null)
                    {
                        currentValue = SelectedSearchItem.DisplayValue;
                    }
                    else if (!string.IsNullOrEmpty(candidateName))
                    {
                        currentValue = string.Format("{0} ({1})", candidateName, affiliationId);
                    }
                }

                return currentValue;
            }
            set
            {
                currentValue = value;
                OnPropertyChanged(null);
            }
        }

        public bool IgnoreWriteIn
        {
            get { return ignoreWriteIn; }
            set
            {
                if (ignoreWriteIn != value)
                {
                    ignoreWriteIn = value;

                    if (ignoreWriteIn)
                    {
                        SelectedSearchItem = null;
                        CurrentValue = null;
                        candidateName = null;
                        affiliationId = null;

                        if (isLoaded)
                        {
                            NeedsVerification = false;

                            PublishFieldCommittedEvent();
                        }
                    }
                    else
                    {
                        if (NeededVerification)
                        {
                            NeedsVerification = true;

                            PublishFieldCommittedEvent();
                        }
                    }

                    if (isLoaded)
                    {
                        IWriteInModification modification;
                        
                        if (SelectedSearchItem != null && !IgnoreWriteIn)
                        {
                            modification = CreateModificationWithAnActualSelection();
                        }
                        else
                        {
                            modification = new WriteInIsIgnoredModification(writeInReadOnlyModel.BallotPaperFieldId);
                        }

                        writeModelHub.AddWriteInModification(modification);
                    }

                    OnPropertyChanged();
                }
            }
        }
        
        private WriteInIsVerifiedModification CreateModificationWithAnActualSelection()
        {
            return new WriteInIsVerifiedModification(
                SelectedSearchItem.AffiliationId, 
                SelectedSearchItem.CandidateName, 
                SelectedSearchItem.AffiliationShortCode, 
                SelectedSearchItem.RankInAffiliation,
                writeInReadOnlyModel.BallotPaperFieldId);

        }

        private void WriteInSelectionChanged()
        {
            if (isLoaded)
            {
                if (SelectedSearchItem != null && !IgnoreWriteIn)
                {
                    var modification = CreateModificationWithAnActualSelection();
                    writeModelHub.AddWriteInModification(modification);

                    if (NeedsVerification)
                    {
                        NeedsVerification = false;

                        PublishFieldCommittedEvent();
                    }
                }
            }
        }

        public bool? IsWriteInFocused
        {
            get { return isWriteInFocused; }
            set
            {
                if (value != isWriteInFocused)
                {
                    isWriteInFocused = value;
                    OnPropertyChanged();
                }
            }
        }

        public bool NeededVerification
        {
            get { return neededVerification; }
            set { throw new NotSupportedException();}
        }

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

        public DelegateCommand WriteInSelectionFromDropDownCommand { get; private set; }

        public DelegateCommand EnterKeyWasPressedOnIgnoreCheckboxCommand { get; private set; }

        public int PageIndex { get; set; }

        public WriteInSelectionItem SelectedSearchItem
        {
            get { return selectedSearchItem; }
            set
            {
                if (selectedSearchItem != null)
                {
                    selectedSearchItem.Selected = false;
                }
                selectedSearchItem = value;
                OnPropertyChanged();
            }
        }

        public bool UserCorrectionHasBeenMade
        {
            get { return !NeedsVerification && CurrentValue != OriginalValue; }
        }

        public int VerificationOrder { get; set; }

        private string OriginalValue
        {
            get
            {
                if (string.IsNullOrEmpty(originalValue))
                {
                    if (string.IsNullOrEmpty(candidateName))
                    {
                        originalValue = writeInReadOnlyModel.ScannerValue;
                    }
                    else
                    {
                        originalValue = string.Format("{0} ({1})", writeInReadOnlyModel.ScannerValue, writeInReadOnlyModel.AffiliationId);
                    }
                }

                return originalValue;
            }
        }

        public void BringToFocus()
        {
            IsWriteInFocused = true;
        }

        public void Reset()
        {
            if (NeededVerification)
            {
                if (writeInReadOnlyModel.NeededVerification)
                {
                    candidateName = null;
                }

                NeedsVerification = true;
                CurrentValue = null;

                ignoreWriteIn = writeInReadOnlyModel.IgnoreWriteIn;
            }
        }

        public void RemainFocusAtThisViewModel()
        {
            BringToFocus();
        }

        private void EnterKeyWasPressedOnIgnoreCheckbox()
        {
            IgnoreWriteIn = !IgnoreWriteIn;
        }

        private void PublishFieldCommittedEvent()
        {
            var actionWasCommmitedArgs = new VerificationWasResolvedEventArgs(this, NeededVerification);
            PublishEvent<VerificationResolvedOnVerifiableViewModelEvent, VerificationWasResolvedEventArgs>(actionWasCommmitedArgs);
            OnPropertyChanged(null);
        }
    }
}

