using System.Collections.Generic;
using Valg.EVA.Skanning.ServicesModel.ElectionConfig.DataProvider;
using Valg.EVA.Skanning.ServicesModel.ElectionConfig.Model;

namespace Valg.EVA.Skanning.Services
{
    public class ElectionConfigEndpoint
    {
        private readonly ICandidateListDataProvider candidateListDataProvider;
        private readonly IElectionConfigDataProvider electionConfigDataProvider;

        public ElectionConfigEndpoint(ICandidateListDataProvider candidateListDataProvider, IElectionConfigDataProvider electionConfigDataProvider)
        {
            this.candidateListDataProvider = candidateListDataProvider;
            this.electionConfigDataProvider = electionConfigDataProvider;
        }

        public ElectionEventResource ElectionEvent(string electionEventId)
        {
            return new ElectionEventResource(electionEventId, candidateListDataProvider, electionConfigDataProvider);
        }

        public class ElectionEventResource
        {
            private readonly string electionEventId;
            private readonly ICandidateListDataProvider candidateListDataProvider;
            private readonly IElectionConfigDataProvider electionConfigDataProvider;

            public ElectionEventResource(string electionEventId, ICandidateListDataProvider candidateListDataProvider, IElectionConfigDataProvider electionConfigDataProvider)
            {
                this.electionEventId = electionEventId;
                this.candidateListDataProvider = candidateListDataProvider;
                this.electionConfigDataProvider = electionConfigDataProvider;
            }

            public ContestResource Contest(string contestId)
            {
                return new ContestResource(electionEventId, contestId, candidateListDataProvider, electionConfigDataProvider);
            }

            public class ContestResource
            {
                private readonly ICandidateListDataProvider candidateListDataProvider;
                private readonly IElectionConfigDataProvider electionConfigDataProvider;
                private readonly string electionEventId;
                private readonly string contestId;

                public ContestResource(string electionEventId, string contestId, ICandidateListDataProvider candidateListDataProvider, IElectionConfigDataProvider electionConfigDataProvider)
                {
                    this.electionEventId = electionEventId;
                    this.contestId = contestId;
                    this.candidateListDataProvider = candidateListDataProvider;
                    this.electionConfigDataProvider = electionConfigDataProvider;
                }

                public PolligDistrictResource PollingDistrict()
                {
                    return new PolligDistrictResource(electionEventId, contestId, candidateListDataProvider, electionConfigDataProvider);
                }

                public class PolligDistrictResource
                {
                    private readonly ICandidateListDataProvider candidateListDataProvider;
                    private readonly IElectionConfigDataProvider electionConfigDataProvider;
                    private readonly string electionEventId;
                    private readonly string contestId;

                    public PolligDistrictResource(string electionEventId, string contestId, ICandidateListDataProvider candidateListDataProvider, IElectionConfigDataProvider electionConfigDataProvider)
                    {
                        this.electionEventId = electionEventId;
                        this.contestId = contestId;
                        this.candidateListDataProvider = candidateListDataProvider;
                        this.electionConfigDataProvider = electionConfigDataProvider;
                    }

                    public List<PollingDistrict> Get()
                    {
                        var pollingDistrictsInContest = new List<PollingDistrict>();
                        var pollingDistrictsInElection = candidateListDataProvider.GetPollingDistricts(electionEventId);
                        var votingCategoriesInContest = electionConfigDataProvider.GetVotingCategoriesInContest(electionEventId, contestId);

                        foreach (var categoryInContest in votingCategoriesInContest)
                        {
                            var pollingDistrictInElection = pollingDistrictsInElection.Find(p => p.Id == categoryInContest.Id);
                            if (pollingDistrictInElection != null)
                            {
                                var pollingDistrict = new PollingDistrict { Id = pollingDistrictInElection.Id, Name = pollingDistrictInElection.Name, VotingCategory = categoryInContest };
                                if (!pollingDistrictsInContest.Exists(pd => pd.Id == pollingDistrict.Id && pd.VotingCategory.Code == pollingDistrict.VotingCategory.Code))
                                {
                                    pollingDistrictsInContest.Add(pollingDistrict);
                                }
                            }
                        }

                        return pollingDistrictsInContest;
                    }
                }
            }
        }
    }
}
