using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Globalization;
using System.Linq;
using Valg.EVA.Skanning.Repositories.SystemSettings;
using Newtonsoft.Json;

namespace Valg.EVA.Skanning.ServicesModel.Internal.SystemSettings
{
    public class SystemSettingsProvider : ISystemSettingsProvider
    {
        private readonly ISystemSettingsRepository systemSettingsRepository;
        private Dictionary<string, string> settingsDictionary = new Dictionary<string, string>();
        private bool dataIsPreloaded;
        private IEnumerable<AdditionalElectionConfiguration> settingMatrix;
        private ReadOnlyCollection<BallotPaperLayoutDescription> layoutDescriptions;

        public SystemSettingsProvider(ISystemSettingsRepository systemSettingsRepository)
        {
            this.systemSettingsRepository = systemSettingsRepository;
        }

        public void PreloadData()
        {
            if (!dataIsPreloaded)
            {
                var systemSettings = systemSettingsRepository.GetSystemSettings();
                settingsDictionary = systemSettings.ToDictionary(systemSetting => systemSetting.Name, systemSetting => systemSetting.Value);
                dataIsPreloaded = true;
            }
        }

        public int GetStampFillPercentageMinimum()
        {
            return GetDictionaryValueAsInt(SystemSettingsKeys.StampFillPercentageMinimum);
        }

        public int GetPersonVoteFillPercentageMinimum()
        {
            return GetDictionaryValueAsInt(SystemSettingsKeys.PersonVoteFillPercentageMinimum);
        }

        public int GetPersonVoteFillPercentageMaximum()
        {
            return GetDictionaryValueAsInt(SystemSettingsKeys.PersonVoteFillPercentageMaximum);
        }

        public int GetStrikeOutFillPercentageMinimum()
        {
            return GetDictionaryValueAsInt(SystemSettingsKeys.StrikeOutFillPercentageMinimum);
        }

        public int GetStrikeOutFillPercentageMaximum()
        {
            return GetDictionaryValueAsInt(SystemSettingsKeys.StrikeOutFillPercentageMaximum);
        }

        public int GetBallotIdLength()
        {
            return GetDictionaryValueAsInt(SystemSettingsKeys.BallotIdLength);
        }

        public int GetBallotNumberLength()
        {
            return GetDictionaryValueAsInt(SystemSettingsKeys.BallotNumberLength);
        }

        public int GetCustomPartyIndex()
        {
            return GetDictionaryValueAsInt(SystemSettingsKeys.CustomPartyIndex);
        }

        public int GetBarcodeLongLength()
        {
            return GetDictionaryValueAsInt(SystemSettingsKeys.BarcodeLongLength);
        }

        public int GetBarcodeShortLength()
        {
            return GetDictionaryValueAsInt(SystemSettingsKeys.BarcodeShortLength);
        }

        public int GetBarcodeShortBoroughLength()
        {
            return GetDictionaryValueAsInt(SystemSettingsKeys.BarcodeShortBoroughLength);
        }

        public string GetProductionCertificateIssuerParams()
        {
            return GetDictionaryValueAsString(SystemSettingsKeys.ProductionCertificateIssuerParams);
        }

        public string GetTrainingCertificateIssuerParams()
        {
            return GetDictionaryValueAsString(SystemSettingsKeys.TrainingCertificateIssuerParams);
        }
	    public float GetMinimumTesseractConfidence()
	    {
		    return GetDictionaryValueAsFloat(SystemSettingsKeys.MinimumTesseractConfidence);
	    }

		public AdditionalElectionConfiguration GetAdditionalElectionConfiguration(string electionEventId, string electionId, string electionGroupId, string contestId)
        {
            var settings = GetSettingMatrix();
            var matchedOnElectionLevel = settings.Where(p => p.ElectionEvent == electionEventId && p.ElectionGroup == electionGroupId && p.ElectionIdentifier == electionId).ToArray();
            var onContestLevel = matchedOnElectionLevel.FirstOrDefault(m => m.ContestIdentifier == contestId);

            return onContestLevel ?? matchedOnElectionLevel.FirstOrDefault();
        }

        public int GetTransferStatusCheckTimeoutInterval()
        {
            return GetDictionaryValueAsInt(SystemSettingsKeys.TransferStatusCheckTimeoutInterval);
        }

        public ReadOnlyCollection<BallotPaperLayoutDescription> GetBallotPaperLayoutDescriptions()
        {
            if (layoutDescriptions == null)
            {
                var json = GetDictionaryValueAsString(SystemSettingsKeys.BallotPaperLayoutDescriptions);
                var collectionFromJson = new List<BallotPaperLayoutDescription>(JsonConvert.DeserializeObject<BallotPaperLayoutDescription[]>(json));
                layoutDescriptions = collectionFromJson.AsReadOnly();
            }

            return layoutDescriptions;
        }

        public bool GetShowBlankBallotInVerification()
        {
            return GetDictionaryValueAsBoolean(SystemSettingsKeys.ShowBlankBallotInVerification);
        }

        private IEnumerable<AdditionalElectionConfiguration> GetSettingMatrix()
        {
            if (settingMatrix == null)
            {
                var json = GetContestCountedByLowerLevelMatrix();
                settingMatrix = JsonConvert.DeserializeObject<List<AdditionalElectionConfiguration>>(json);
            }
            return settingMatrix;
        }

        private string GetContestCountedByLowerLevelMatrix()
        {
            return GetDictionaryValueAsString(SystemSettingsKeys.ContestCountedByLowerLevelMatrix);
        }

        public string GetGeneralMunicipalityAffiliationList()
        {
            return GetDictionaryValueAsString(SystemSettingsKeys.GeneralMunicipalityAffiliationList);
        }

        public string GetGeneralCountyAffiliationList()
        {
            return GetDictionaryValueAsString(SystemSettingsKeys.GeneralCountyAffiliationList);
        }

        public string GetGeneralOsloDistrictAffiliationList()
        {
            return GetDictionaryValueAsString(SystemSettingsKeys.GeneralOsloDistrictAffiliationList);
        }

        public string GetGeneralParliamentAffiliationList()
        {
            return GetDictionaryValueAsString(SystemSettingsKeys.GeneralParliamentAffiliationList);
        }

        public int GetDataRefreshInterval()
        {
            return GetDictionaryValueAsInt(SystemSettingsKeys.DataRefreshInterval);
        }

        public string GetOsloDistrictList()
        {
            return GetDictionaryValueAsString(SystemSettingsKeys.OsloDistrictList);
        }

        public List<int> GetValidLengthsForBallotId()
        {
            return new List<int> { GetBallotIdLength(), GetGeneralBallotIdLength() };
        }

        public int GetGeneralBallotIdLength()
        {
            return GetDictionaryValueAsInt(SystemSettingsKeys.GeneralBallotIdLength);
        }

        public int GetGeneralBallotPartyVoteFillPercentageMinimum()
        {
            return GetDictionaryValueAsInt(SystemSettingsKeys.GeneralBallotPartyVoteFillPercentageMinimum);
        }

        public int GetGeneralBallotPartyVoteFillPercentageMaximum()
        {
            return GetDictionaryValueAsInt(SystemSettingsKeys.GeneralBallotPartyVoteFillPercentageMaximum);
        }

        private int GetDictionaryValueAsInt(string key)
        {
            PreloadData();
            return Convert.ToInt32(settingsDictionary[key]);
        }

        private bool GetDictionaryValueAsBoolean(string key)
        {
            PreloadData();
            return Convert.ToBoolean(settingsDictionary[key]);
        }

        private string GetDictionaryValueAsString(string key)
        {
            PreloadData();
            return settingsDictionary[key];
        }

	    private float GetDictionaryValueAsFloat(string key)
	    {
		    PreloadData();
		    return float.Parse(settingsDictionary[key],CultureInfo.InvariantCulture);
	    }
	}
}
