using Valg.EVA.Skanning.Contracts.CommonEnums;
using Valg.EVA.Skanning.Entity.SerializedEntities.FieldValueModel;
using Valg.EVA.Skanning.ServicesModel.ElectionConfig.DataProvider;
using Valg.EVA.Skanning.ServicesModel.Internal;
using Valg.EVA.Skanning.ServicesModel.Internal.Serializers;
using System;
using System.Collections.Generic;
using System.Linq;
using Valg.EVA.Skanning.Diagnostics;
using Valg.EVA.Skanning.ServicesModel.ServiceContracts.Scan.Write;

namespace Valg.EVA.Skanning.Services.Scan
{
    public class WriteInFieldGenerator : IWriteInFieldGenerator
    {
        private readonly IElectionConfigDataProvider electionConfigDataProvider;

        public WriteInFieldGenerator(IElectionConfigDataProvider electionConfigDataProvider)
        {
            this.electionConfigDataProvider = electionConfigDataProvider;
        }

        public CreateEmptyWriteInFieldPlaceholdersResult CreateEmptyWriteInFieldPlaceholders(ScannedField[] alreadyRecognizedWriteIns, string barcodeLong)
        {
            var result = new CreateEmptyWriteInFieldPlaceholdersResult();
            try
            {
                var addedFields = new List<ScannedField>();

                var electionEventId = barcodeLong.GetElectionEventIdFromBarcodeLong();
                var contestId = barcodeLong.GetContestIdFromBarcodeLong();

                var countMetrics = electionConfigDataProvider.GetCountMetricsForContest(electionEventId, contestId);

                if (countMetrics.HasWriteIns.GetValueOrDefault())
                {
                    var maxWriteInForContest = electionConfigDataProvider.GetMaxWriteInForContest(electionEventId, contestId);
                    if (maxWriteInForContest > 0)
                    {
                        var usedIndices = new HashSet<int>(alreadyRecognizedWriteIns.Where(f => f.FieldIndex <= maxWriteInForContest).Select(f => f.FieldIndex));

                        for (int i = 1; i <= maxWriteInForContest; i++)
                        {
                            if (!usedIndices.Contains(i))
                            {
                                var emptyWriteInField = new ScannedField
                                {
                                    Value = "",
                                    FieldType = FieldType.Candidate,
                                    FieldIndex = i,
                                    NeedsVerification = false
                                };

                                var writeInData = new WriteInData { NeedsVerification = false, NeededVerification = false, IgnoreWriteIn = true };
                                emptyWriteInField.SerializeWriteInDataToJson(writeInData);
                                addedFields.Add(emptyWriteInField);
                            }
                        }
                    }
                }
                result.NewWriteIns = addedFields.ToArray();
            }
            catch (Exception e)
            {
                EvaSkanningEventSource.Log.GeneratingWriteInPlaceholderFieldsFailed(e.ToString());
                result.HasDatabaseErrors = true;
                result.DatabaseError = e;
            }
            return result;
        }
    }
}
