using Valg.EVA.Skanning.ContainerExtensions;
using Valg.EVA.Skanning.Contracts.CommonEnums;
using Valg.EVA.Skanning.ServicesModel.ServiceContracts.Verification.Read;
using Valg.EVA.Skanning.UserInterfaceElements.BallotPaperImage;
using Valg.EVA.Skanning.ServicesModel.ElectionConfig.DataProvider;
using Valg.EVA.Skanning.ServicesModel.ElectionConfig.Model;
using System.Collections.Generic;
using System.Linq;
using System.Windows.Media.Imaging;
using Valg.EVA.Skanning.Contracts;
using Valg.EVA.Skanning.Services.SystemSettings;
using Valg.EVA.Skanning.Services.Verification;
using Valg.EVA.Skanning.ServicesModel.Internal.SystemSettings;
using Valg.EVA.Skanning.Verify.Startup.Preview;
using Valg.EVA.Skanning.Verify.Startup.VerifyBallotPaper.BallotNumber;
using Valg.EVA.Skanning.Verify.Startup.VerifyBallotPaper.Candidate;
using Valg.EVA.Skanning.Verify.Startup.VerifyBallotPaper.Header;
using Valg.EVA.Skanning.Verify.Startup.VerifyBallotPaper.RenumberStrikeout;
using Valg.EVA.Skanning.Verify.Startup.VerifyBallotPaper.Stamp;
using Valg.EVA.Skanning.Verify.Startup.VerifyBallotPaper.WriteIns;

namespace Valg.EVA.Skanning.Verify.Startup.VerifyBallotPaper.PageXOfY
{
    public class VerifyBallotPaperSubPagesViewModelsBuilder : IVerifyBallotPaperSubPagesViewModelsBuilder
    {
        private readonly IBallotPaperImageLoader ballotPaperImageLoader;
        private readonly ITypedFactory typedFactory;
        private readonly ICandidateListDataProvider candidateListDataProvider;
        private readonly IElectionConfigDataProvider electionConfigDataProvider;
        private readonly ISystemSettingsService systemSettingsService;

        public VerifyBallotPaperSubPagesViewModelsBuilder(IBallotPaperImageLoader ballotPaperImageLoader, ITypedFactory typedFactory,
            ICandidateListDataProvider candidateListDataProvider, IElectionConfigDataProvider electionConfigDataProvider, ISystemSettingsService systemSettingsService)
        {
            this.ballotPaperImageLoader = ballotPaperImageLoader;
            this.typedFactory = typedFactory;
            this.candidateListDataProvider = candidateListDataProvider;
            this.electionConfigDataProvider = electionConfigDataProvider;
            this.systemSettingsService = systemSettingsService;
        }

        public void AddSubPagesToViewModel(IVerifyBallotPaperViewModel verifyBallotPaperViewModel)
        {
            var bitmapInfo = ballotPaperImageLoader.GetBallotPaperBitmaps(verifyBallotPaperViewModel.BallotPaper.Id, verifyBallotPaperViewModel.BallotPaper.BallotPaperType);
            var candidateSections = GetCandidatePageSections(verifyBallotPaperViewModel.BallotPaper.BallotPaperType);
            
            verifyBallotPaperViewModel.Preview.SetModel(bitmapInfo, verifyBallotPaperViewModel.BallotPaper.Id, verifyBallotPaperViewModel.BallotPaper.BoxCountingId);

            AddStampVerificationPage(verifyBallotPaperViewModel, bitmapInfo, candidateSections.Length);

            RebuildPages(verifyBallotPaperViewModel, verifyBallotPaperViewModel.BallotPaper.RejectionReason, bitmapInfo, candidateSections, false, null);
        }


        public void UpdateSubPagesOnViewModel(IVerifyBallotPaperViewModel verifyBallotPaperViewModel, BallotNumberUpdate ballotNumberUpdate)
        {
            var bitmapInfo = ballotPaperImageLoader.GetBallotPaperBitmaps(verifyBallotPaperViewModel.BallotPaper.Id, verifyBallotPaperViewModel.BallotPaper.BallotPaperType);

            var candidateBallotPaperType = BlankBallotPaperTypeClass.IsBallotPaperTypeBlank(verifyBallotPaperViewModel.BallotPaper.BallotPaperType)
                ? BlankBallotPaperTypeClass.CandidateBallotPaperType[verifyBallotPaperViewModel.BallotPaper.BallotPaperType]
                : verifyBallotPaperViewModel.BallotPaper.BallotPaperType;
            CandidateSection[] candidateSections = GetCandidatePageSections(candidateBallotPaperType);

            RebuildPages(verifyBallotPaperViewModel, verifyBallotPaperViewModel.WriteModelHub.RejectionReason, bitmapInfo, candidateSections, true, ballotNumberUpdate);
        }

        private void RebuildPages(IVerifyBallotPaperViewModel verifyBallotPaperViewModel, RejectionReasonType rejectionReason,
            BallotPaperImageInformation bitmapInfo, CandidateSection[] candidateSections, bool resetCandidatesAndWriteIns, BallotNumberUpdate ballotNumberUpdate)
        {
            if (rejectionReason != RejectionReasonType.NoOfficialStamp)
            {
                AddBallotNumberPage(verifyBallotPaperViewModel, bitmapInfo, rejectionReason);
                AddAffiliationPage(verifyBallotPaperViewModel, bitmapInfo, rejectionReason);
            }

            var ignoreCandidates = ballotNumberUpdate == null ? verifyBallotPaperViewModel.BallotPaper.IgnoreCandidates : ballotNumberUpdate.IgnoreCandidates;

            if (!ignoreCandidates
                && !RejectionReasonsCollections.AllActualRejectionReasons.Contains(rejectionReason))
            {
                RebuildCandidatesAndWriteIns(bitmapInfo, candidateSections, verifyBallotPaperViewModel, resetCandidatesAndWriteIns, ballotNumberUpdate);
            }
        }

        private void RebuildCandidatesAndWriteIns(BallotPaperImageInformation bitmapInfo, CandidateSection[] candidateSections,
            IVerifyBallotPaperViewModel verifyBallotPaperViewModel, bool isReset, BallotNumberUpdate ballotNumberUpdate)
        {
            verifyBallotPaperViewModel.RemoveBallotNumberDependentBallotPages();
            var countMetricsForContest = electionConfigDataProvider.GetCountMetricsForContest(verifyBallotPaperViewModel.BallotPaper.ElectionEventId, verifyBallotPaperViewModel.BallotPaper.ContestId);

            Affiliation affiliation;
            if (ballotNumberUpdate == null)
            {
                affiliation = candidateListDataProvider.GetAffiliation(
                    verifyBallotPaperViewModel.BallotPaper.ElectionEventId,
                    verifyBallotPaperViewModel.BallotPaper.ContestId,
                    verifyBallotPaperViewModel.BallotPaper.AffiliationShortCode);

            }
            else
            {
                affiliation = candidateListDataProvider.GetAffiliation(
                   ballotNumberUpdate.ElectionEventId,
                   ballotNumberUpdate.ContestId,
                   ballotNumberUpdate.AffiliationShortCode);
            }

            if (affiliation != null && affiliation.Candidates.Any())
            {
                if (countMetricsForContest.HasPersonalVotes.GetValueOrDefault())
                {
                    MapCandidates(verifyBallotPaperViewModel, affiliation.Candidates, isReset);
                    BuildCandidatePages(bitmapInfo, candidateSections, verifyBallotPaperViewModel, affiliation, ballotNumberUpdate, countMetricsForContest);
                }
                if (countMetricsForContest.HasRenumbering.GetValueOrDefault() && countMetricsForContest.HasStrikeouts.GetValueOrDefault())
                {
                    MapRenumberStrikeout(verifyBallotPaperViewModel, affiliation.Candidates, isReset);
                    BuildRenumberStrikeoutPages(bitmapInfo, candidateSections, verifyBallotPaperViewModel, affiliation, ballotNumberUpdate, countMetricsForContest);
                }
                
                AddWriteInPageIfAppropriate(bitmapInfo, verifyBallotPaperViewModel, isReset, ballotNumberUpdate);
            }
        }

        private CandidateSection[] GetCandidatePageSections(BallotPaperType ballotPaperType)
        {
            var layoutDescription = TemplateBasedLayoutDescriptionProvider.GetBallotPaperLayoutDescription(ballotPaperType);
            if (layoutDescription != BallotPaperLayoutDescription.Empty)
            {
                return layoutDescription.CandidateSections;
            }

            return CandidateSectionHelper.GetDefaultCandidatePageSections();
        }

        private void AddBallotNumberPage(IVerifyBallotPaperViewModel verifyBallotPaperViewModel, BallotPaperImageInformation bitmapInfo, RejectionReasonType rejectionReason)
        {
            if (!verifyBallotPaperViewModel.BallotPages.Pages.Any(p => p.ViewModel is IBallotNumberViewModel))
            {
                verifyBallotPaperViewModel.BallotNumberViewModel.SetModel(
                    verifyBallotPaperViewModel.BallotPaper.BallotNo,
                    verifyBallotPaperViewModel.Counting.ElectionEventId,
                    verifyBallotPaperViewModel.Counting.ElectionGroup,
                    verifyBallotPaperViewModel.Counting.ElectionIdentifier,
                    verifyBallotPaperViewModel.Counting.ContestId,
                    verifyBallotPaperViewModel.Counting.IsCurrentlyCountedByTopLevelCountingAuthority(),
                    rejectionReason,
                    verifyBallotPaperViewModel.BallotPaper.BallotPaperType.IsGeneralBallotPaperType());

                var tooltip = new PageXOfYNavigationTooltip(Resources.Language.VerifyLanguageString.GotoBallotNumberPage);

                PreviewBallotPaperImageViewModel previewViewModel;
                if (BallotPaperTypeIsGeneral(verifyBallotPaperViewModel.BallotPaper.BallotPaperType))
                {
                    previewViewModel = CreatePreviewViewModel(bitmapInfo, 1, BallotPaperContentAreaType.BallotNo);
                }
                else
                {
                    if (BallotPaperTypeIsBlank(verifyBallotPaperViewModel.BallotPaper.BallotPaperType))
                    {
                        previewViewModel = CreatePreviewViewModel(bitmapInfo, GetCandidatePageSections(verifyBallotPaperViewModel.BallotPaper.BallotPaperType).Length, BallotPaperContentAreaType.Blank, BallotPaperContentAreaType.AffiliationName, BallotPaperContentAreaType.BallotNo);
                    }
                    else
                    {
                        previewViewModel = CreatePreviewViewModel(bitmapInfo, GetCandidatePageSections(verifyBallotPaperViewModel.BallotPaper.BallotPaperType).Length, BallotPaperContentAreaType.AffiliationName, BallotPaperContentAreaType.BallotNo);
                    }
                }

                verifyBallotPaperViewModel.AddBallotPage(verifyBallotPaperViewModel.BallotNumberViewModel, tooltip, previewViewModel);
            }
        }

        private void AddAffiliationPage(IVerifyBallotPaperViewModel verifyBallotPaperViewModel, BallotPaperImageInformation bitmapInfo, RejectionReasonType rejectionReason)
        {
            if (!verifyBallotPaperViewModel.BallotPages.Pages.Any(p => p.ViewModel is IAffiliationHeaderViewModel))
            {
                verifyBallotPaperViewModel.AffiliationHeaderViewModel.SetModel(
                    verifyBallotPaperViewModel.BallotPaper.BallotNo,
                    verifyBallotPaperViewModel.Counting.ElectionEventId,
                    verifyBallotPaperViewModel.Counting.ElectionGroup,
                    verifyBallotPaperViewModel.Counting.ElectionIdentifier,
                    verifyBallotPaperViewModel.Counting.ContestId,
                    verifyBallotPaperViewModel.Counting.IsCurrentlyCountedByTopLevelCountingAuthority(),
                    rejectionReason,
                    verifyBallotPaperViewModel.BallotPaper.BallotPaperType.IsGeneralBallotPaperType(),verifyBallotPaperViewModel.BallotPaper.AffiliationNames);

                var tooltip = new PageXOfYNavigationTooltip(Resources.Language.VerifyLanguageString.GotoBallotNumberPage);

                PreviewBallotPaperImageViewModel previewViewModel;
                if (BallotPaperTypeIsGeneral(verifyBallotPaperViewModel.BallotPaper.BallotPaperType))
                {
                    previewViewModel = CreatePreviewViewModel(bitmapInfo, 1, BallotPaperContentAreaType.BallotNo);
                }
                else
                {
                    previewViewModel = CreatePreviewViewModel(bitmapInfo, GetCandidatePageSections(verifyBallotPaperViewModel.BallotPaper.BallotPaperType).Length, BallotPaperContentAreaType.AffiliationName);
                }

                verifyBallotPaperViewModel.AddBallotPage(verifyBallotPaperViewModel.AffiliationHeaderViewModel, tooltip, previewViewModel);
            }
        }

        private bool BallotPaperTypeIsBlank(BallotPaperType ballotPaperType)
        {
            return (ballotPaperType == BallotPaperType.CountyBlank2 || ballotPaperType == BallotPaperType.CountyBlank3 || ballotPaperType == BallotPaperType.MunicipalityBlank2 ||
                    ballotPaperType == BallotPaperType.OsloDistrictBlank || ballotPaperType == BallotPaperType.ParliamentBlank || ballotPaperType == BallotPaperType.MunicipalityBlank3);

           
        }


        private bool BallotPaperTypeIsGeneral(BallotPaperType ballotPaperType)
        {
            return (ballotPaperType == BallotPaperType.CountyGeneral || ballotPaperType == BallotPaperType.MunicipalityGeneral || ballotPaperType == BallotPaperType.OsloDistrictGeneral || ballotPaperType == BallotPaperType.ParliamentGeneral);
        }

        private void AddStampVerificationPage(IVerifyBallotPaperViewModel verifyBallotPaperViewModel, BallotPaperImageInformation bitmapInfo, int numberOfCandidateSections)
        {
            if (!verifyBallotPaperViewModel.BallotPages.Pages.Any(p => p.ViewModel is IStampVerificationPageViewModel))
            {
                var tooltip = new PageXOfYNavigationTooltip(Resources.Language.VerifyLanguageString.GotoStampVerificationPage);

                var previewViewModel = CreatePreviewViewModel(bitmapInfo, numberOfCandidateSections, BallotPaperContentAreaType.Stamp);

                verifyBallotPaperViewModel.AddBallotPage(verifyBallotPaperViewModel.StampVerificationPageViewModel, tooltip, previewViewModel);
            }
        }

        private PreviewBallotPaperImageViewModel CreatePreviewViewModelCandidates(BallotPaperImageInformation bitmapInfo, int sectionSectionIndex, int? numberOfCandidateSections)
        {
            var images = new List<BitmapSource>();

            var contentAreaDescription = bitmapInfo.LayoutDescription.ContentAreaDescriptions.SingleOrDefault(s => s.ContentAreaType == BallotPaperContentAreaType.Candidates && s.Index == sectionSectionIndex);
            if (contentAreaDescription != null)
            {
                images.Add(ballotPaperImageLoader.CreateCroppedBitmap(contentAreaDescription, bitmapInfo, numberOfCandidateSections));
            }
            else
            {
                images.Add(bitmapInfo.Front);
                images.Add(bitmapInfo.Back);
            }

            return new PreviewBallotPaperImageViewModel(images.ToArray());
        }

        private PreviewBallotPaperImageViewModel CreatePreviewViewModel(BallotPaperImageInformation bitmapInfo, int? numberOfCandidateSections, params BallotPaperContentAreaType[] contentAreaTypes)
        {
            var images = new List<BitmapSource>();

            foreach (var contentAreaType in contentAreaTypes)
            {
                if (bitmapInfo.LayoutDescription != BallotPaperLayoutDescription.Empty)
                {
                   foreach (var contentAreaDescription in bitmapInfo.LayoutDescription.ContentAreaDescriptions.Where(p => p.ContentAreaType == contentAreaType && !p.Hidden))
                   {
                       images.Add(ballotPaperImageLoader.CreateCroppedBitmap(contentAreaDescription, bitmapInfo, numberOfCandidateSections));
                    }
                }
                else
                {
                    images.Add(bitmapInfo.Front);
                    images.Add(bitmapInfo.Back);
                    break;
                }
            }

            return new PreviewBallotPaperImageViewModel(images.ToArray());
        }

        private void BuildCandidatePages(BallotPaperImageInformation bitmapInfo, CandidateSection[] candidateSections, IVerifyBallotPaperViewModel verifyBallotPaperViewModel, Affiliation affiliation, BallotNumberUpdate ballotNumberUpdate, CountMetricsForContest countMetricsForContest)
        {
            foreach (var section in candidateSections)
            {
                var candidatesForPage = CandidateSectionHelper.GetCandidatesForPage(verifyBallotPaperViewModel.AllCandidates, section);

                if (candidatesForPage.Count > 0)
                {
                    var tooltipText = string.Format(Resources.Language.VerifyLanguageString.GotoCandidatePageTemplate,
                        OrderedNumberTextHelper.GetOrderNumberText(verifyBallotPaperViewModel.BallotPages.PagedViewModels.Count(p => p is CandidatePageViewModel) + 1));

                    var tooltip = new PageXOfYNavigationTooltip(tooltipText);

                    var previewViewModel = CreatePreviewViewModelCandidates(bitmapInfo, section.SectionIndex, candidateSections.Length);

                    var electionEventId = ballotNumberUpdate == null ? verifyBallotPaperViewModel.BallotPaper.ElectionEventId : ballotNumberUpdate.ElectionEventId;
                    var contestId = ballotNumberUpdate == null ? verifyBallotPaperViewModel.BallotPaper.ContestId : ballotNumberUpdate.ContestId;
                    var electionId = ballotNumberUpdate == null ? verifyBallotPaperViewModel.BallotPaper.ElectionId : ballotNumberUpdate.ElectionId;

                    var contest = electionConfigDataProvider.GetContest(electionEventId, contestId);
                    var election = electionConfigDataProvider.GetElection(electionEventId, electionId);

                    if (countMetricsForContest.HasPersonalVotes.GetValueOrDefault())
                    {
                        var candidatePage = new CandidatePageViewModel(contest, election, affiliation, candidatesForPage);
                        verifyBallotPaperViewModel.AddBallotPage(candidatePage, tooltip, previewViewModel);
                    }
                }
            }
        }

        private void BuildRenumberStrikeoutPages(BallotPaperImageInformation bitmapInfo, CandidateSection[] candidateSections, IVerifyBallotPaperViewModel verifyBallotPaperViewModel, Affiliation affiliation, BallotNumberUpdate ballotNumberUpdate, CountMetricsForContest countMetricsForContest)
        {
            foreach (var section in candidateSections)
            {
                var renumberStrikeoutsForPage = CandidateSectionHelper.GetRenumberStrikeoutsForPage(verifyBallotPaperViewModel.RenumberStrikeouts, section);

                if (renumberStrikeoutsForPage.Count > 0)
                {
                    var tooltipText = string.Format(Resources.Language.VerifyLanguageString.GotoCandidatePageTemplate,
                        OrderedNumberTextHelper.GetOrderNumberText(verifyBallotPaperViewModel.BallotPages.PagedViewModels.Count(p => p is CandidatePageViewModel) + 1));

                    var tooltip = new PageXOfYNavigationTooltip(tooltipText);

                    var previewViewModel = CreatePreviewViewModelCandidates(bitmapInfo, section.SectionIndex, candidateSections.Length);

                    var electionEventId = ballotNumberUpdate == null ? verifyBallotPaperViewModel.BallotPaper.ElectionEventId : ballotNumberUpdate.ElectionEventId;
                    var contestId = ballotNumberUpdate == null ? verifyBallotPaperViewModel.BallotPaper.ContestId : ballotNumberUpdate.ContestId;
                    var electionId = ballotNumberUpdate == null ? verifyBallotPaperViewModel.BallotPaper.ElectionId : ballotNumberUpdate.ElectionId;

                    var contest = electionConfigDataProvider.GetContest(electionEventId, contestId);
                    var election = electionConfigDataProvider.GetElection(electionEventId, electionId);

                    if (countMetricsForContest.HasRenumbering.GetValueOrDefault() && countMetricsForContest.HasStrikeouts.GetValueOrDefault())
                    {
                        var renumberStrikeoutPage = new RenumberStrikeoutPageViewModel(contest, election, affiliation, renumberStrikeoutsForPage);
                        verifyBallotPaperViewModel.AddBallotPage(renumberStrikeoutPage, tooltip, previewViewModel);
                    }
                }
            }
        }

        private void AddWriteInPageIfAppropriate(BallotPaperImageInformation bitmapInfo, IVerifyBallotPaperViewModel verifyBallotPaperViewModel, bool isReset, BallotNumberUpdate ballotNumberUpdate)
        {
            var electionEventId = ballotNumberUpdate == null ? verifyBallotPaperViewModel.BallotPaper.ElectionEventId : ballotNumberUpdate.ElectionEventId;
            var contestId = ballotNumberUpdate == null ? verifyBallotPaperViewModel.BallotPaper.ContestId : ballotNumberUpdate.ContestId;

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

            if (countMetricsForContest.HasWriteIns.GetValueOrDefault())
            {
                var writeInPageViewModel = CreateWriteInPageViewModel(verifyBallotPaperViewModel.BallotPaper, isReset, ballotNumberUpdate);

                var tooltip = new PageXOfYNavigationTooltip(Resources.Language.VerifyLanguageString.GotoWriteInsPage);

                var previewViewModel = CreatePreviewViewModel(bitmapInfo, GetCandidatePageSections(verifyBallotPaperViewModel.BallotPaper.BallotPaperType).Length, BallotPaperContentAreaType.WriteIn);

                verifyBallotPaperViewModel.AddBallotPage(writeInPageViewModel, tooltip, previewViewModel);
            }
        }

        private IWriteInPageViewModel CreateWriteInPageViewModel(BallotPaper ballotPaperToVerify, bool isReset, BallotNumberUpdate ballotNumberUpdate)
        {
            var writeInPageViewModel = typedFactory.Create<IWriteInPageViewModel>();
            
            var electionEventId = ballotNumberUpdate == null ? ballotPaperToVerify.ElectionEventId : ballotNumberUpdate.ElectionEventId;
            var contestId = ballotNumberUpdate == null ? ballotPaperToVerify.ContestId : ballotNumberUpdate.ContestId;
            var affiliationShortCode = ballotNumberUpdate == null ? ballotPaperToVerify.AffiliationShortCode : ballotNumberUpdate.AffiliationShortCode;

            var candidates = candidateListDataProvider.GetWriteInCandidates(electionEventId, contestId, affiliationShortCode);
            writeInPageViewModel.CandidateList = CreateSelectionItemCandidateList(candidates);

            var maxWriteIn = electionConfigDataProvider.GetMaxWriteInForContest(ballotPaperToVerify.ElectionEventId, ballotPaperToVerify.ContestId).GetValueOrDefault();

            MapWriteInViewModel(ballotPaperToVerify, writeInPageViewModel, isReset, maxWriteIn);

            return writeInPageViewModel;
        }

        private static List<WriteInSelectionItem> CreateSelectionItemCandidateList(List<ServicesModel.ElectionConfig.Model.Candidate> candidates)
        {
            return candidates.Select(candidate => new WriteInSelectionItem
            {
                CandidateName = candidate.NameLine,
                AffiliationId = candidate.AffiliationId,
                AffiliationShortCode = candidate.AffiliationShortCode,
                RankInAffiliation = candidate.RankInAffiliation
            }).ToList();
        }

        private void MapWriteInViewModel(BallotPaper ballotPaperToVerify, IWriteInPageViewModel writeInPageViewModel, bool isReset, int maxWriteIns)
        {
            var writeInsToUse = ballotPaperToVerify.WriteIns;
            if (isReset)
            {
                writeInsToUse = ballotPaperToVerify.InitialWriteIns;
            }

            writeInPageViewModel.ClearWriteIns();

            if (writeInsToUse != null)
            {
                foreach (var writeIn in writeInsToUse)
                {
                    if (maxWriteIns == 0 || writeIn.FieldIndex <= maxWriteIns)
                    {
                        var writeInViewModel = typedFactory.Create<WriteInViewModel>();
                        writeInViewModel.SetModel(writeIn, isReset);
                        writeInPageViewModel.WriteIns.Add(writeInViewModel);
                    }
                }
            }
        }

        private void MapCandidates(IVerifyBallotPaperViewModel ballotPaperVerifyViewModel, List<ServicesModel.ElectionConfig.Model.Candidate> affiliationCandidates, bool isReset)
        {
            ballotPaperVerifyViewModel.ClearCandidates();
            
            foreach (var affiliationCandidate in affiliationCandidates)
            {
                var candidateViewModel = typedFactory.Create<CandidateViewModel>();
                candidateViewModel.CandidateRank = affiliationCandidate.RankInAffiliation;
                candidateViewModel.Name = affiliationCandidate.NameLine;

                var candidatePersonVote = ballotPaperVerifyViewModel.BallotPaper.GetCandidatePersonVoteForCandidate(affiliationCandidate.RankInAffiliation);

                int? underlyingFieldId = null;

                if (candidatePersonVote != null)
                {
                    candidateViewModel.PersonVotedAsInterpretedByScanner = candidatePersonVote.PersonVotedAsInterpretedByScanner;
                    candidateViewModel.PersonVotedAsGivenByCorrection = candidatePersonVote.PersonVotedAsGivenByCorrection;
                    candidateViewModel.NeededVerification = candidatePersonVote.NeededVerification;
                    candidateViewModel.NeedsVerification = candidatePersonVote.NeedsVerification;
                    candidateViewModel.IsCreatedFirstTimeByVerifier = candidatePersonVote.IsCreatedFirstTimeByVerifier;

                    if (isReset)
                    {
                        candidateViewModel.Reset();
                    }

                    underlyingFieldId = candidatePersonVote.UnderlyingFieldId;
                }

                candidateViewModel.BallotPaperId = ballotPaperVerifyViewModel.BallotPaper.Id;
                candidateViewModel.CandidatePersonVoteFieldId = underlyingFieldId;
                ballotPaperVerifyViewModel.AddCandidateViewModel(candidateViewModel);
            }
        }

        private void MapRenumberStrikeout(IVerifyBallotPaperViewModel ballotPaperVerifyViewModel, List<ServicesModel.ElectionConfig.Model.Candidate> affiliationCandidates, bool isReset)
        {
            ballotPaperVerifyViewModel.ClearRenumberStrikeouts();
            var renumberValuesAlreadySelected = new List<int>();

            if (!isReset)
            {
                renumberValuesAlreadySelected = GetRenumberValues(ballotPaperVerifyViewModel, affiliationCandidates);
            }

            foreach (var affiliationCandidate in affiliationCandidates)
            {
                var renumberStrikeoutViewModel = typedFactory.Create<RenumberStrikeoutViewModel>();
                renumberStrikeoutViewModel.SetPossibleRenumberValues(GetPossibleRenumberValues(affiliationCandidate.RankInAffiliation, affiliationCandidates, renumberValuesAlreadySelected));
                renumberStrikeoutViewModel.CandidateRank = affiliationCandidate.RankInAffiliation;
                renumberStrikeoutViewModel.Name = affiliationCandidate.NameLine;

                var renumberStrikeoutReadOnly = ballotPaperVerifyViewModel.BallotPaper.GetRenumberStrikeoutForCandidate(affiliationCandidate.RankInAffiliation);
                if (renumberStrikeoutReadOnly != null)
                {
                    renumberStrikeoutViewModel.SetModel(renumberStrikeoutReadOnly);

                    if (isReset)
                    {
                        renumberStrikeoutViewModel.Reset();
                    }
                }

                ballotPaperVerifyViewModel.AddRenumberStrikeoutViewModel(renumberStrikeoutViewModel);
            }
        }

        private static List<int> GetRenumberValues(IVerifyBallotPaperViewModel ballotPaperVerifyViewModel, List<ServicesModel.ElectionConfig.Model.Candidate> affiliationCandidates)
        {
            var renumbers = new List<int>();
            foreach (var affiliationCandidate in affiliationCandidates)
            {
                var renumberStrikeoutReadOnly = ballotPaperVerifyViewModel.BallotPaper.GetRenumberStrikeoutForCandidate(affiliationCandidate.RankInAffiliation);
                if (renumberStrikeoutReadOnly != null)
                {
                    if (renumberStrikeoutReadOnly.Renumber.HasValue)
                    {
                        renumbers.Add(renumberStrikeoutReadOnly.Renumber.Value);
                    }
                }
            }
            return renumbers;
        }

        private static List<int> GetPossibleRenumberValues(int rankInAffiliation, List<ServicesModel.ElectionConfig.Model.Candidate> allCandidatesForAffiliation, List<int> renumbersAlreadySelected)
        {
            var possibleRenumberValues = Enumerable.Range(1, allCandidatesForAffiliation.Count).ToList();
            possibleRenumberValues.Remove(rankInAffiliation);
            foreach (var renumber in renumbersAlreadySelected)
            {
                possibleRenumberValues.Remove(renumber);
            }
            return possibleRenumberValues;
        }
    }
}
