using System.Linq;
using Valg.EVA.Skanning.Contracts.CommonEnums;

namespace Valg.EVA.Skanning.Scan.ReadSoftContracts.Model
{
    public class ScannableBallotPaperType
    {
        private readonly BallotPaperType ballotPaperType;
        private readonly string formDefinitionName;
        private readonly ScannableFieldType[] fieldTypesForThisBallotPaperType;

        private static readonly ScannableFieldType[] municipalityFieldTypes =
        {
            ScannableFieldType.BallotID,
            ScannableFieldType.BallotNo,
            ScannableFieldType.MarkIncr,
            ScannableFieldType.Candidate,
            ScannableFieldType.Stamp,
            ScannableFieldType.AffiliationName,
            ScannableFieldType.ContestName
        };
        
        private static readonly ScannableFieldType[] countyFieldTypes =
        {
            ScannableFieldType.BallotID,
            ScannableFieldType.BallotNo,
            ScannableFieldType.MarkIncr,
            ScannableFieldType.Stamp,
            ScannableFieldType.AffiliationName
        };

        private static readonly ScannableFieldType[] unknownFieldTypes =
        {
            ScannableFieldType.BallotID,
            ScannableFieldType.BallotNo,
            ScannableFieldType.Stamp
        };

        private static readonly ScannableFieldType[] generalFieldTypes =
        {
            ScannableFieldType.BallotID,
            ScannableFieldType.BallotNo,
            ScannableFieldType.Ref_opt,
            ScannableFieldType.Stamp,
            ScannableFieldType.AffiliationName
        };

        private static readonly ScannableFieldType[] osloDistrictGeneralFieldTypes =
        {
            ScannableFieldType.BallotID,
            ScannableFieldType.BallotNo,
            ScannableFieldType.Ref_opt,
            ScannableFieldType.Stamp, 
            ScannableFieldType.MultipleStamps,
            ScannableFieldType.AffiliationName
        };

        private static readonly ScannableFieldType[] osloDistrictFieldTypes =
        {
            ScannableFieldType.BallotID,
            ScannableFieldType.BallotNo,
            ScannableFieldType.MarkIncr,
            ScannableFieldType.Candidate,
            ScannableFieldType.Stamp, 
            ScannableFieldType.MultipleStamps,
            ScannableFieldType.AffiliationName
        };

        private static readonly ScannableFieldType[] osloDistrictBlankFieldTypes =
        {
            ScannableFieldType.BallotID,
            ScannableFieldType.BallotNo,
            ScannableFieldType.MarkIncr,
            ScannableFieldType.Stamp, 
            ScannableFieldType.MultipleStamps,
            ScannableFieldType.AffiliationName
        };

        private static readonly ScannableFieldType[] parliamentFieldTypes =
        {
            ScannableFieldType.BallotID,
            ScannableFieldType.BallotNo,
            ScannableFieldType.MarkDecr,
            ScannableFieldType.Ca_renumber,
            ScannableFieldType.Stamp,
            ScannableFieldType.AffiliationName
        };

        private static readonly ScannableFieldType[] blankFieldTypes =
        {
            ScannableFieldType.BallotID,
            ScannableFieldType.BallotNo,
            ScannableFieldType.Stamp,
            ScannableFieldType.MarkIncr,
            ScannableFieldType.AffiliationName
        };

        private static readonly ScannableFieldType[] parliamentPersonalFieldTypes =
        {
            ScannableFieldType.BallotID,
            ScannableFieldType.BallotNo,
            ScannableFieldType.MarkIncr,
            ScannableFieldType.Stamp
        };

        private static readonly ScannableFieldType[] qualityCheckFieldTypes =
        {
            ScannableFieldType.BallotID,
            ScannableFieldType.BallotNo,
            ScannableFieldType.MarkDecr,
            ScannableFieldType.Ca_renumber,
            ScannableFieldType.Stamp
        };

        public static readonly ScannableBallotPaperType Unknown = new ScannableBallotPaperType(BallotPaperType.Unknown, string.Empty, unknownFieldTypes);
        public static readonly ScannableBallotPaperType ParliamentGeneral = new ScannableBallotPaperType(BallotPaperType.ParliamentGeneral, "GenStor2", generalFieldTypes);
        public static readonly ScannableBallotPaperType Parliament = new ScannableBallotPaperType(BallotPaperType.Parliament, "Storting2", parliamentFieldTypes);
        public static readonly ScannableBallotPaperType ParliamentPersonal = new ScannableBallotPaperType(BallotPaperType.ParliamentPersonal, "StorPers2", parliamentPersonalFieldTypes);
        public static readonly ScannableBallotPaperType Municipality3 = new ScannableBallotPaperType(BallotPaperType.Municipality3, "Kommune3", municipalityFieldTypes);
        public static readonly ScannableBallotPaperType Municipality3X = new ScannableBallotPaperType(BallotPaperType.Municipality3X, "Kommune3X", municipalityFieldTypes);
        public static readonly ScannableBallotPaperType Municipality2 = new ScannableBallotPaperType(BallotPaperType.Municipality2, "Kommune2", municipalityFieldTypes);
        public static readonly ScannableBallotPaperType MunicipalityGeneral = new ScannableBallotPaperType(BallotPaperType.MunicipalityGeneral, "GenKomm2", generalFieldTypes);
        public static readonly ScannableBallotPaperType County2 = new ScannableBallotPaperType(BallotPaperType.County2, "Fylke2", countyFieldTypes);
        public static readonly ScannableBallotPaperType County3 = new ScannableBallotPaperType(BallotPaperType.County3, "Fylke3", countyFieldTypes);
        public static readonly ScannableBallotPaperType CountyGeneral = new ScannableBallotPaperType(BallotPaperType.CountyGeneral, "GenFylk2", generalFieldTypes);
        public static readonly ScannableBallotPaperType OsloDistrictGeneral = new ScannableBallotPaperType(BallotPaperType.OsloDistrictGeneral, "GenOslo2", osloDistrictGeneralFieldTypes);
        public static readonly ScannableBallotPaperType OsloDistrict = new ScannableBallotPaperType(BallotPaperType.OsloDistrict, "Oslo2", osloDistrictFieldTypes);
        public static readonly ScannableBallotPaperType ParliamentBlank = new ScannableBallotPaperType(BallotPaperType.ParliamentBlank, "StorBlank", blankFieldTypes);
        public static readonly ScannableBallotPaperType MunicipalityBlank3 = new ScannableBallotPaperType(BallotPaperType.MunicipalityBlank3, "KomBlank3", blankFieldTypes);
        public static readonly ScannableBallotPaperType MunicipalityBlank2 = new ScannableBallotPaperType(BallotPaperType.MunicipalityBlank2, "KomBlank2", blankFieldTypes);
        public static readonly ScannableBallotPaperType CountyBlank2 = new ScannableBallotPaperType(BallotPaperType.CountyBlank2, "FylBlank2", blankFieldTypes);
        public static readonly ScannableBallotPaperType CountyBlank3 = new ScannableBallotPaperType(BallotPaperType.CountyBlank3, "FylBlank3", blankFieldTypes);
        public static readonly ScannableBallotPaperType OsloDistrictBlank = new ScannableBallotPaperType(BallotPaperType.OsloDistrictBlank, "OslBlank2", osloDistrictBlankFieldTypes);
        public static readonly ScannableBallotPaperType QualityCheck = new ScannableBallotPaperType(BallotPaperType.QualityCheck, "Kvalitet", qualityCheckFieldTypes);

        public static readonly ScannableBallotPaperType[] AllScannableBallotPaperTypes =
        {
            ParliamentGeneral, Parliament,  ParliamentBlank, 
            Municipality2, Municipality3, Municipality3X, MunicipalityBlank2, MunicipalityBlank3,  MunicipalityGeneral,
            County2, County3, CountyBlank2, CountyBlank3, CountyGeneral,
            OsloDistrictGeneral, OsloDistrict, OsloDistrictBlank, 
            QualityCheck
        };

        public static ScannableBallotPaperType GetFromFormDefinition(string formDefinitionName)
        {
            var scannableBallotPaperType = AllScannableBallotPaperTypes.SingleOrDefault(s => s.FormDefinitionName == formDefinitionName);
            if (scannableBallotPaperType == null)
            {
                return Unknown;
            }

            return scannableBallotPaperType;
        }

        private ScannableBallotPaperType(BallotPaperType ballotPaperType, string formDefinitionName, ScannableFieldType[] fieldTypesForThisBallotPaperType)
        {
            this.ballotPaperType = ballotPaperType;
            this.formDefinitionName = formDefinitionName;
            this.fieldTypesForThisBallotPaperType = fieldTypesForThisBallotPaperType;
        }

        public BallotPaperType BallotPaperType
        {
            get { return ballotPaperType; }
        }
        public string FormDefinitionName
        {
            get { return formDefinitionName; }
        }
        public ScannableFieldType[] FieldTypesForThisBallotPaperType
        {
            get { return fieldTypesForThisBallotPaperType; }
        }
        public ScannableFieldType[] RequiredFieldTypes
        {
            get { return FieldTypesForThisBallotPaperType.Where(f => f.IsRequired).ToArray(); } 
        }
    }
}
