using System;
using System.Collections.Generic;
using System.IO;
using System.Xml.Serialization;
using Valg.EVA.Skanning.Oasis.EMLStandard;
using Valg.EVA.Skanning.ServicesModel.Internal;
using Valg.EVA.Skanning.ServicesModel.ElectionConfig.Model;

namespace Valg.EVA.Skanning.ServicesModel.ElectionConfig.DataProvider
{
    public class AffiliationMapper : IAffiliationMapper
    {
        public List<Affiliation> MapAffiliations(IList<string> affilationsXml)
        {
            var xmlRoot = new XmlRootAttribute("Affiliation") { Namespace = "urn:oasis:names:tc:evs:schema:eml" };
            var serializer = new XmlSerializer(typeof(CandidateListElectionContestAffiliation), xmlRoot);
            var allAffiliationsForContest = new List<Affiliation>();

            foreach (var affiliationXml in affilationsXml)
            {
                using (var stringReader = new StringReader(affiliationXml))
                {
                    var affiliationFromEml = (CandidateListElectionContestAffiliation)serializer.Deserialize(stringReader);
                    var mappedAffiliation = MapAffiliation(affiliationFromEml);
                    allAffiliationsForContest.Add(mappedAffiliation);
                }
            }

            return allAffiliationsForContest;
        }

        private Affiliation MapAffiliation(CandidateListElectionContestAffiliation affiliationFromEml)
        {
            var affiliation = new Affiliation();
            affiliation.AffiliationId = affiliationFromEml.AffiliationIdentifier.Id;
            affiliation.AffiliationShortCode = affiliationFromEml.AffiliationIdentifier.ShortCode;
            affiliation.RegisteredName = affiliationFromEml.AffiliationIdentifier.RegisteredName;

            affiliation.SetCandidates(MapCandidates(affiliationFromEml.Candidate));

            return affiliation;
        }

        private List<Candidate> MapCandidates(CandidateStructure[] candidatesToMap)
        {
            var candidates = new List<Candidate>();

            if (candidatesToMap != null)
            {
                foreach (var candidateStructure in candidatesToMap)
                {
                    var candidate = new Candidate();

                    var nameLineElementIndex = Array.FindIndex(candidateStructure.ItemsElementName, item => item == ItemsChoiceType.NameLine);
                    candidate.NameLine = candidateStructure.Items[nameLineElementIndex].ToString();

                    var candidateShortCode = candidateStructure
                        .Items.TypedItem<CandidateIdentifierStructure>()
                        .ShortCode1;

                    candidate.RankInAffiliation = int.Parse(candidateShortCode);

                    candidates.Add(candidate);
                }
            }

            return candidates;
        }
    }
}
