using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using Valg.EVA.Skanning.Contracts;
using Valg.EVA.Skanning.Contracts.CommonEnums;
using Valg.EVA.Skanning.Entity.ReadModel;
using Valg.EVA.Skanning.ServicesModel.Internal;
using Valg.EVA.Skanning.ServicesModel.ServiceContracts.Verification.Write;

namespace Valg.EVA.Skanning.Commands.SaveBallotPaperVerifications
{
    public class UpdateBallotCommonFeaturesFilter : IFilter<UpdateBallotCommonFeaturesFilterInput, bool>
    {
        private readonly FieldValueOperationsHelper fieldValueOperationsHelper;

        public UpdateBallotCommonFeaturesFilter(FieldValueOperationsHelper fieldValueOperationsHelper)
        {
            this.fieldValueOperationsHelper = fieldValueOperationsHelper;
        }

        public bool Execute(UpdateBallotCommonFeaturesFilterInput input)
        {
            if (input.ShouldExecute)
            {
                var command = input.Command;
                var currentFieldValues = input.CurrentFieldValues;

                InsertStamp(command, currentFieldValues);

                var keepPersonalVotingFeatures = true;

                if (command.BallotNumberVerification != null)
                {
                    InsertBallotNo(command, currentFieldValues);

                    int ballotPaperId = command.BallotPaperId;
                    fieldValueOperationsHelper.ResetFieldValues(ballotPaperId,
                        new List<FieldType> { FieldType.Candidate, FieldType.Ca_renumber, FieldType.MarkIncr, FieldType.MarkDecr }, 
                        currentFieldValues);

                    if (command.BallotNumberVerification.IgnoreCandidates)
                        keepPersonalVotingFeatures = false;
                }
                else if (command.IsRejectedForAnyReason)
                {
                    int ballotPaperId = command.BallotPaperId;
                    fieldValueOperationsHelper.ResetFieldValues(ballotPaperId,
                        new List<FieldType>
                        {
                            FieldType.BallotNo, FieldType.Candidate, FieldType.MarkIncr, FieldType.Ca_renumber, FieldType.MarkDecr
                        }, 
                        currentFieldValues);
                    keepPersonalVotingFeatures = false;
                }

                return keepPersonalVotingFeatures;
            }

            return false;
        }

        private void InsertStamp(SaveBallotPaperVerificationsCommand command, ReadOnlyCollection<BallotPaperFieldValue> currentFieldValues)
        {
            if (command.StampVerification != null)
            {
                var stampValue = GetStampValue(command.StampVerification).ToString();
                var currentFieldValue = currentFieldValues.SingleOrDefault(f => f.IsStampField());
                if (currentFieldValue == null)
                    fieldValueOperationsHelper.InsertBallotPaperField(stampValue, command.BallotPaperId, null, FieldType.Stamp, command.ChangedBy);
                else
                    fieldValueOperationsHelper.InsertBallotPaperFieldValue(stampValue, currentFieldValue.BallotPaperFieldId, ValueSourceType.Verify, command.ChangedBy);
            }
        }

        private void InsertBallotNo(SaveBallotPaperVerificationsCommand command, ReadOnlyCollection<BallotPaperFieldValue> currentFieldValues)
        {
            var currentFieldValue = currentFieldValues.SingleOrDefault(f => f.IsBallotNoField());
            if (currentFieldValue == null)
                fieldValueOperationsHelper.InsertBallotPaperField(command.BallotNumberVerification.NewValue, command.BallotPaperId, null, FieldType.BallotNo, command.ChangedBy);
            else
                fieldValueOperationsHelper.InsertBallotPaperFieldValue(command.BallotNumberVerification.NewValue, currentFieldValue.BallotPaperFieldId, ValueSourceType.Verify, command.ChangedBy);
        }

        private int GetStampValue(StampVerification stampVerification)
        {
            return stampVerification.StampIsValid ? ScannerFieldValueTemplateValues.ValidStamp : ScannerFieldValueTemplateValues.InvalidStamp;
        }
    }
}
