using System.Collections.Generic;
using System.Text.RegularExpressions;

namespace Valg.EVA.Skanning.Identity.Area
{
    public static class ElectionLevelExtensions
    {
        public static bool ShouldAddRoles(this AreaDescription.ElectionLevel level)
        {
            return level < AreaDescription.ElectionLevel.ElectionEvent;
        }
    }

    public class AreaDescription
    {
        private const int ElectionEventLength = 6;


        public static List<AreaDescription> CreateAreaDescriptions(string[] areaContextIds)
        {
            var areaDescriptions = new List<AreaDescription>();
            foreach (string areaContextId in areaContextIds)
            {
                areaDescriptions.Add(new AreaDescription(areaContextId));
            }
            return areaDescriptions;
        }

        public AreaDescription(string areaContextId)
        {
            TokenAreaContextId = areaContextId;

            if (string.IsNullOrWhiteSpace(areaContextId))
            {
                IsValid = false;
            }
            else if (IsWrongFormat(areaContextId))
            {
                IsValid = false;
            }
            else
            {
                Parse(areaContextId);
                IsValid = true;
            }
        }

        public enum ElectionLevel
        {
            Unknown = 100, ElectionEvent = 5, County = 4, Municipality = 3, Borough = 2, PollingDistrict = 1
        }

        public ElectionLevel Level { get; private set; }

        public string TokenAreaContextId { get; private set; }

        public string AreaName { get; set; }

        public bool IsValid { get; private set; }

        public string ElectionEventId { get; private set; }

        public string CountyId { get; private set; }

        public string CountyCode { get; private set; }

        public string MunicipalityId { get; private set; }

        public string Borough { get; private set; }

        public string PollingDistrict { get; private set; }

        public string EmlAreaContextId
        {
            get
            {
                if (Level == ElectionLevel.ElectionEvent)
                {
                    return TokenAreaContextId.Remove(0, ElectionEventLength);
                }
                else
                {
                    
                    return TokenAreaContextId.Remove(0, ElectionEventLength + 1);
                }
            }
        }
        

        public string ConvertAreaContextId(ElectionLevel electionLevel)
        {
            if (IsPossibleConversion(electionLevel))
            {
                string newAreaContextId = "";
                switch (electionLevel)
                {
                    case ElectionLevel.ElectionEvent:
                        newAreaContextId = string.Format("{0}", ElectionEventId);
                        break;

                    case ElectionLevel.County:
                        newAreaContextId = string.Format("{0}.{1}", ElectionEventId, CountyId);
                        break;

                    case ElectionLevel.Municipality:
                        newAreaContextId = string.Format("{0}.{1}.{2}", ElectionEventId, CountyId, MunicipalityId);
                        break;
                    case ElectionLevel.Borough:
                        newAreaContextId = string.Format("{0}.{1}.{2}.{3}", ElectionEventId, CountyId, MunicipalityId, Borough);
                        break;
                    case ElectionLevel.PollingDistrict:
                        newAreaContextId = string.Format("{0}.{1}.{2}.{3}.{4}", ElectionEventId, CountyId, MunicipalityId, Borough, PollingDistrict);
                        break;
                }
                return newAreaContextId;
            }
            else
            {
                throw new System.ArgumentException("Not a valid conversion");
            }
        }

        private bool IsWrongFormat(string areaContextId)
        {
            bool isWrongFormat = true;
            int length = areaContextId.Length;
            if (IsValidLength(length) && IsOnlyNumberAndDots(areaContextId))
            {
                isWrongFormat = false;
            }
            return isWrongFormat;
        }

        
        
        
        private bool IsOnlyNumberAndDots(string areaContextId)
        {
            Regex regex = new Regex(@"^\d+(\.\d+)*$");
            return regex.IsMatch(areaContextId);
        }

        private bool IsValidLength(int length)
        {
            return length == 6 || length == 12 || length == 17 || length == 24 || length == 29;
        }

        private void Parse(string areaContextId)
        {
            string[] parts = areaContextId.Split(new char[] { '.' });

            this.ElectionEventId = parts[0];
            Level = ElectionLevel.ElectionEvent;

            if (parts.Length >= 3)
            {
                this.CountyId = string.Format("{0}.{1}", parts[1], parts[2]);
                this.CountyCode = parts[2];
                Level = ElectionLevel.County;
            }

            if (parts.Length >= 4)
            {
                this.MunicipalityId = parts[3];
                Level = ElectionLevel.Municipality;
            }
            if (parts.Length >= 5)
            {
                this.Borough = parts[4];
                Level = ElectionLevel.Borough;
            }
            if (parts.Length >= 6)
            {
                this.PollingDistrict = parts[5];
                Level = ElectionLevel.PollingDistrict;
            }
        }

        private bool IsPossibleConversion(ElectionLevel wantedElectionLevel)
        {
            return this.Level <= wantedElectionLevel;
        }
    }
}
