using System.Collections.Generic;
using System.Dynamic;
using System.IO;
using System.Linq;
using EHF;
using Valg.EVA.Skanning.Scan.ReadSoftContracts.Model;

namespace Valg.EVA.Skanning.Scan.Api
{
    public class ScannedFormMapper
    {
        private readonly IFieldValueAssignerFactory fieldValueAssignerFactory;

        public ScannedFormMapper(IFieldValueAssignerFactory fieldValueAssignerFactory)
        {
            this.fieldValueAssignerFactory = fieldValueAssignerFactory;
        }

        public ScannedForm MapScannedForm(IEHF_IForm form)
        {
            dynamic classicObject = form.GetClassicObject();

            var ret = new ScannedForm()
            {
                Name = form.Name,
                FormFields = GetFormFields(form.Fields, ScannableBallotPaperType.GetFromFormDefinition(form.Name))
            };
            if (classicObject != null)
            {
                ret.ArchiveFrontImageBytes = classicObject.Bytes[0];
                ret.ArchiveBackImageBytes = classicObject.Bytes[1];
                ret.BackRotatedDegrees = classicObject.BackRotatedDegrees;
                ret.FrontRotatedDegrees = classicObject.FrontRotatedDegrees;
                ret.ScannedOrder = classicObject.ScannedOrder;
            }
            return ret;
        }

        private Dictionary<ScannableFieldType, List<ScannedField>> GetFormFields(IEHF_IFieldCollection fields, ScannableBallotPaperType scannableBallotPaperType)
        {
            var dictionary = new Dictionary<ScannableFieldType, List<ScannedField>>();

            foreach (var scannableFieldType in scannableBallotPaperType.FieldTypesForThisBallotPaperType)
            {
                dictionary.Add(scannableFieldType, new List<ScannedField>());
            }

            foreach (IEHF_COMField field in fields)
            {
                var fieldType = scannableBallotPaperType.FieldTypesForThisBallotPaperType.Single(f => f.FieldName == field.Name);

                var scannedField = new ScannedField();
                scannedField.FieldType = fieldType.FieldType;

                var valueAssigner = fieldValueAssignerFactory.GetFieldValueAssigner(fieldType);
                scannedField.Value = valueAssigner.AssignValue(field);

                if (!fieldType.TreatAllIndexedFieldsAsOne)
                {
                    scannedField.FieldIndex = field.Index;
                }

                dictionary[fieldType].Add(scannedField);
            }

            return dictionary;
        }
    }
}
