using Microsoft.Extensions.Configuration;
using Phares.Shared;
using System.Text.Json;

namespace View_by_Distance.Tests.Models.Binder;

public class Configuration
{

    public bool? CheckDFaceAndUpWriteDates { get; set; }
    public bool? CheckJsonForDistanceResults { get; set; }
    public string[]? CopyFacesAndSaveFaceLandmarkForOutputResolutions { get; set; }
    public int? CrossDirectoryMaxItemsInDistanceCollection { get; set; }
    public bool? DeletePossibleDuplicates { get; set; }
    public int? DistanceFactor { get; set; }
    public bool? DistanceMoveUnableToMatch { get; set; }
    public int? DistancePixelDistanceTolerance { get; set; }
    public bool? DistanceRenameToMatch { get; set; }
    public int? EyeThreshold { get; set; }
    public int? FaceAreaPermyriad { get; set; }
    public int? FaceConfidencePercent { get; set; }
    public int? FaceDistanceHiddenImageFactor { get; set; }
    public int? FaceDistancePermyriad { get; set; }
    public string? FocusDirectory { get; set; }
    public string? FocusModel { get; set; }
    public bool? ForceFaceLastWriteTimeToCreationTime { get; set; }
    public bool? ForceMetadataLastWriteTimeToCreationTime { get; set; }
    public bool? ForceResizeLastWriteTimeToCreationTime { get; set; }
    public string? GenealogicalDataCommunicationFile { get; set; }
    public string[]? IgnoreExtensions { get; set; }
    public string[]? JLinks { get; set; }
    public string[]? LoadOrCreateThenSaveDistanceResultsForOutputResolutions { get; set; }
    public string[]? LoadOrCreateThenSaveImageFacesResultsForOutputResolutions { get; set; }
    public bool? LoadPhotoPrismLocations { get; set; }
    public float? LocationContainerDistanceTolerance { get; set; }
    public int? LocationDigits { get; set; }
    public int? LocationFactor { get; set; }
    public bool? LookForAbandoned { get; set; }
    public string? MappingDefaultName { get; set; }
    public bool? MappingUseDeterministicHashCodeUnknownFaceKeyValuePairsForAddToMapping { get; set; }
    public bool? MappingUseDeterministicHashCodeUnknownFaceKeyValuePairsForSaveMapping { get; set; }
    public string[]? MixedYearRelativePaths { get; set; }
    public string? ModelDirectory { get; set; }
    public string? ModelName { get; set; }
    public int? NumberOfJitters { get; set; }
    public int? NumberOfTimesToUpsample { get; set; }
    public string? OutputExtension { get; set; }
    public int? OutputQuality { get; set; }
    public string[]? OutputResolutions { get; set; }
    public bool? OverrideForFaceImages { get; set; }
    public bool? OverrideForFaceLandmarkImages { get; set; }
    public bool? OverrideForResizeImages { get; set; }
    public int? PersonBirthdayFirstYear { get; set; }
    public string? PersonBirthdayFormat { get; set; }
    public string? PersonCharacters { get; set; }
    public int? PersonCharactersCopyCount { get; set; }
    public string? PersonKeyFormat { get; set; }
    public string? PredictorModelName { get; set; }
    public bool? PropertiesChangedForDistance { get; set; }
    public bool? PropertiesChangedForFaces { get; set; }
    public bool? PropertiesChangedForIndex { get; set; }
    public bool? PropertiesChangedForMetadata { get; set; }
    public bool? PropertiesChangedForResize { get; set; }
    public int? RadomUseBirthdayMinimum { get; set; }
    public int[]? RangeDaysDeltaTolerance { get; set; }
    public float[]? RangeDistanceTolerance { get; set; }
    public float[]? RangeFaceAreaTolerance { get; set; }
    public float[]? RangeFaceConfidence { get; set; }
    public float[]? RectangleIntersectMinimums { get; set; }
    public bool? Reverse { get; set; }
    public string[]? SaveBlurHashForOutputResolutions { get; set; }
    public string[]? SaveFaceDistancesForOutputResolutions { get; set; }
    public string[]? SaveFaceLandmarkForOutputResolutions { get; set; }
    public string[]? SaveFilteredOriginalImagesFromJLinksForOutputResolutions { get; set; }
    public bool? SaveFullYearOfRandomFiles { get; set; }
    public bool? SaveIndividually { get; set; }
    public string[]? SaveMappedForOutputResolutions { get; set; }
    public string[]? SavePropertyShortcutsForOutputResolutions { get; set; }
    public string[]? SaveRandomForOutputResolutions { get; set; }
    public bool? SaveResizedSubfiles { get; set; }
    public string[]? SaveShortcutsForOutputResolutions { get; set; }
    public bool? SaveSortingWithoutPerson { get; set; }
    public string[]? SkipNotSkipDirectories { get; set; }
    public int? SkipOlderThanDays { get; set; }
    public int? SkipPersonWithMoreThen { get; set; }
    public bool? SkipSearch { get; set; }
    public int? SortingMaximumPerFaceShouldBeHigh { get; set; }
    public int? SortingMaximumPerKey { get; set; }
    public int? SortingMinimumToUseSigma { get; set; }
    public bool? TestDistanceResults { get; set; }
    public int? UseFilterTries { get; set; }
    public string[]? ValidKeyWordsToIgnoreInRandom { get; set; }
    public string[]? ValidResolutions { get; set; }

    public override string ToString()
    {
        string result = JsonSerializer.Serialize(this, new JsonSerializerOptions() { WriteIndented = true });
        return result;
    }

#pragma warning restore csharp_preserve_single_line_statements

    private static Models.Configuration Get(Configuration? configuration, Property.Models.Configuration propertyConfiguration)
    {
        Models.Configuration result;
        if (configuration is null) throw new NullReferenceException(nameof(configuration));
        if (configuration.CheckDFaceAndUpWriteDates is null) throw new NullReferenceException(nameof(configuration.CheckDFaceAndUpWriteDates));
        if (configuration?.CheckDFaceAndUpWriteDates is null) throw new NullReferenceException(nameof(configuration.CheckDFaceAndUpWriteDates));
        if (configuration?.CheckJsonForDistanceResults is null) throw new NullReferenceException(nameof(configuration.CheckJsonForDistanceResults));
        // if (configuration?.CopyFacesAndSaveFaceLandmarkForOutputResolutions is null) throw new NullReferenceException(nameof(configuration.CopyFacesAndSaveFaceLandmarkForOutputResolutions));
        if (configuration?.CrossDirectoryMaxItemsInDistanceCollection is null) throw new NullReferenceException(nameof(configuration.CrossDirectoryMaxItemsInDistanceCollection));
        if (configuration?.DeletePossibleDuplicates is null) throw new NullReferenceException(nameof(configuration.DeletePossibleDuplicates));
        if (configuration?.DistanceFactor is null) throw new NullReferenceException(nameof(configuration.DistanceFactor));
        if (configuration?.DistanceMoveUnableToMatch is null) throw new NullReferenceException(nameof(configuration.DistanceMoveUnableToMatch));
        if (configuration?.DistancePixelDistanceTolerance is null) throw new NullReferenceException(nameof(configuration.DistancePixelDistanceTolerance));
        if (configuration?.DistanceRenameToMatch is null) throw new NullReferenceException(nameof(configuration.DistanceRenameToMatch));
        if (configuration?.EyeThreshold is null) throw new NullReferenceException(nameof(configuration.EyeThreshold));
        if (configuration?.FaceAreaPermyriad is null) throw new NullReferenceException(nameof(configuration.FaceAreaPermyriad));
        if (configuration?.FaceConfidencePercent is null) throw new NullReferenceException(nameof(configuration.FaceConfidencePercent));
        if (configuration?.FaceDistanceHiddenImageFactor is null) throw new NullReferenceException(nameof(configuration.FaceDistanceHiddenImageFactor));
        if (configuration?.FaceDistancePermyriad is null) throw new NullReferenceException(nameof(configuration.FaceDistancePermyriad));
        if (configuration?.FocusDirectory is null) throw new NullReferenceException(nameof(configuration.FocusDirectory));
        if (configuration?.FocusModel is null) throw new NullReferenceException(nameof(configuration.FocusModel));
        if (configuration?.ForceFaceLastWriteTimeToCreationTime is null) throw new NullReferenceException(nameof(configuration.ForceFaceLastWriteTimeToCreationTime));
        if (configuration?.ForceMetadataLastWriteTimeToCreationTime is null) throw new NullReferenceException(nameof(configuration.ForceMetadataLastWriteTimeToCreationTime));
        if (configuration?.ForceResizeLastWriteTimeToCreationTime is null) throw new NullReferenceException(nameof(configuration.ForceResizeLastWriteTimeToCreationTime));
        if (configuration?.GenealogicalDataCommunicationFile is null) throw new NullReferenceException(nameof(configuration.GenealogicalDataCommunicationFile));
        // if (configuration?.IgnoreExtensions is null) throw new NullReferenceException(nameof(configuration.IgnoreExtensions));
        // if (configuration?.JLinks is null) throw new NullReferenceException(nameof(configuration.JLinks));
        // if (configuration?.LoadOrCreateThenSaveDistanceResultsForOutputResolutions is null) throw new NullReferenceException(nameof(configuration.LoadOrCreateThenSaveDistanceResultsForOutputResolutions));
        // if (configuration?.LoadOrCreateThenSaveImageFacesResultsForOutputResolutions is null) throw new NullReferenceException(nameof(configuration.LoadOrCreateThenSaveImageFacesResultsForOutputResolutions));
        if (configuration?.LoadPhotoPrismLocations is null) throw new NullReferenceException(nameof(configuration.LoadPhotoPrismLocations));
        // if (configuration?.LocationContainerDistanceTolerance is null) throw new NullReferenceException(nameof(configuration.LocationContainerDistanceTolerance));
        if (configuration?.LocationDigits is null) throw new NullReferenceException(nameof(configuration.LocationDigits));
        if (configuration?.LocationFactor is null) throw new NullReferenceException(nameof(configuration.LocationFactor));
        if (configuration?.LookForAbandoned is null) throw new NullReferenceException(nameof(configuration.LookForAbandoned));
        if (configuration?.MappingDefaultName is null) throw new NullReferenceException(nameof(configuration.MappingDefaultName));
        if (configuration?.MappingUseDeterministicHashCodeUnknownFaceKeyValuePairsForAddToMapping is null) throw new NullReferenceException(nameof(configuration.MappingUseDeterministicHashCodeUnknownFaceKeyValuePairsForAddToMapping));
        if (configuration?.MappingUseDeterministicHashCodeUnknownFaceKeyValuePairsForSaveMapping is null) throw new NullReferenceException(nameof(configuration.MappingUseDeterministicHashCodeUnknownFaceKeyValuePairsForSaveMapping));
        // if (configuration?.MixedYearRelativePaths is null) throw new NullReferenceException(nameof(configuration.MixedYearRelativePaths));
        if (configuration?.ModelDirectory is null) throw new NullReferenceException(nameof(configuration.ModelDirectory));
        if (configuration?.ModelName is null) throw new NullReferenceException(nameof(configuration.ModelName));
        if (configuration?.OutputExtension is null) throw new NullReferenceException(nameof(configuration.OutputExtension));
        if (configuration?.OutputQuality is null) throw new NullReferenceException(nameof(configuration.OutputQuality));
        // if (configuration?.OutputResolutions is null) throw new NullReferenceException(nameof(configuration.OutputResolutions));
        if (configuration?.OverrideForFaceImages is null) throw new NullReferenceException(nameof(configuration.OverrideForFaceImages));
        if (configuration?.OverrideForFaceLandmarkImages is null) throw new NullReferenceException(nameof(configuration.OverrideForFaceLandmarkImages));
        if (configuration?.OverrideForResizeImages is null) throw new NullReferenceException(nameof(configuration.OverrideForResizeImages));
        if (configuration?.PersonBirthdayFirstYear is null) throw new NullReferenceException(nameof(configuration.PersonBirthdayFirstYear));
        if (configuration?.PersonBirthdayFormat is null) throw new NullReferenceException(nameof(configuration.PersonBirthdayFormat));
        if (configuration?.PersonCharacters is null) throw new NullReferenceException(nameof(configuration.PersonCharacters));
        if (configuration?.PersonCharactersCopyCount is null) throw new NullReferenceException(nameof(configuration.PersonCharactersCopyCount));
        if (configuration?.PersonKeyFormat is null) throw new NullReferenceException(nameof(configuration.PersonKeyFormat));
        if (configuration?.PredictorModelName is null) throw new NullReferenceException(nameof(configuration.PredictorModelName));
        if (configuration?.PropertiesChangedForDistance is null) throw new NullReferenceException(nameof(configuration.PropertiesChangedForDistance));
        if (configuration?.PropertiesChangedForFaces is null) throw new NullReferenceException(nameof(configuration.PropertiesChangedForFaces));
        if (configuration?.PropertiesChangedForIndex is null) throw new NullReferenceException(nameof(configuration.PropertiesChangedForIndex));
        if (configuration?.PropertiesChangedForMetadata is null) throw new NullReferenceException(nameof(configuration.PropertiesChangedForMetadata));
        if (configuration?.PropertiesChangedForResize is null) throw new NullReferenceException(nameof(configuration.PropertiesChangedForResize));
        if (configuration?.RadomUseBirthdayMinimum is null) throw new NullReferenceException(nameof(configuration.RadomUseBirthdayMinimum));
        // if (configuration?.RangeDaysDeltaTolerance is null) throw new NullReferenceException(nameof(configuration.RangeDaysDeltaTolerance));
        // if (configuration?.RangeDistanceTolerance is null) throw new NullReferenceException(nameof(configuration.RangeDistanceTolerance));
        // if (configuration?.RangeFaceAreaTolerance is null) throw new NullReferenceException(nameof(configuration.RangeFaceAreaTolerance));
        // if (configuration?.RangeFaceConfidence is null) throw new NullReferenceException(nameof(configuration.RangeFaceConfidence));
        // if (configuration?.RectangleIntersectMinimums is null) throw new NullReferenceException(nameof(configuration.RectangleIntersectMinimums));
        if (configuration?.Reverse is null) throw new NullReferenceException(nameof(configuration.Reverse));
        // if (configuration?.SaveBlurHashForOutputResolutions is null) throw new NullReferenceException(nameof(configuration.SaveBlurHashForOutputResolutions));
        // if (configuration?.SaveFaceDistancesForOutputResolutions is null) throw new NullReferenceException(nameof(configuration.SaveFaceDistancesForOutputResolutions));
        // if (configuration?.SaveFaceLandmarkForOutputResolutions is null) throw new NullReferenceException(nameof(configuration.SaveFaceLandmarkForOutputResolutions));
        // if (configuration?.SaveFilteredOriginalImagesFromJLinksForOutputResolutions is null) throw new NullReferenceException(nameof(configuration.SaveFilteredOriginalImagesFromJLinksForOutputResolutions));
        if (configuration?.SaveFullYearOfRandomFiles is null) throw new NullReferenceException(nameof(configuration.SaveFullYearOfRandomFiles));
        if (configuration?.SaveIndividually is null) throw new NullReferenceException(nameof(configuration.SaveIndividually));
        // if (configuration?.SaveMappedForOutputResolutions is null) throw new NullReferenceException(nameof(configuration.SaveMappedForOutputResolutions));
        // if (configuration?.SavePropertyShortcutsForOutputResolutions is null) throw new NullReferenceException(nameof(configuration.SavePropertyShortcutsForOutputResolutions));
        // if (configuration?.SaveRandomForOutputResolutions is null) throw new NullReferenceException(nameof(configuration.SaveRandomForOutputResolutions));
        if (configuration?.SaveResizedSubfiles is null) throw new NullReferenceException(nameof(configuration.SaveResizedSubfiles));
        // if (configuration?.SaveShortcutsForOutputResolutions is null) throw new NullReferenceException(nameof(configuration.SaveShortcutsForOutputResolutions));
        if (configuration?.SaveSortingWithoutPerson is null) throw new NullReferenceException(nameof(configuration.SaveSortingWithoutPerson));
        // if (configuration?.SkipNotSkipDirectories is null) throw new NullReferenceException(nameof(configuration.SkipNotSkipDirectories));
        // if (configuration?.SkipOlderThanDays is null) throw new NullReferenceException(nameof(configuration.SkipOlderThanDays));
        // if (configuration?.SkipPersonWithMoreThen is null) throw new NullReferenceException(nameof(configuration.SkipPersonWithMoreThen));
        if (configuration?.SkipSearch is null) throw new NullReferenceException(nameof(configuration.SkipSearch));
        if (configuration?.SortingMaximumPerFaceShouldBeHigh is null) throw new NullReferenceException(nameof(configuration.SortingMaximumPerFaceShouldBeHigh));
        if (configuration?.SortingMaximumPerKey is null) throw new NullReferenceException(nameof(configuration.SortingMaximumPerKey));
        if (configuration?.SortingMinimumToUseSigma is null) throw new NullReferenceException(nameof(configuration.SortingMinimumToUseSigma));
        if (configuration?.TestDistanceResults is null) throw new NullReferenceException(nameof(configuration.TestDistanceResults));
        if (configuration?.UseFilterTries is null) throw new NullReferenceException(nameof(configuration.UseFilterTries));
        // if (configuration?.ValidKeyWordsToIgnoreInRandom is null) throw new NullReferenceException(nameof(configuration.ValidKeyWordsToIgnoreInRandom));
        // if (configuration?.ValidResolutions is null) throw new NullReferenceException(nameof(configuration.ValidResolutions));
        result = new(propertyConfiguration,
                     configuration.CheckDFaceAndUpWriteDates.Value,
                     configuration.CheckJsonForDistanceResults.Value,
                     configuration.CopyFacesAndSaveFaceLandmarkForOutputResolutions ?? Array.Empty<string>(),
                     configuration.CrossDirectoryMaxItemsInDistanceCollection.Value,
                     configuration.DeletePossibleDuplicates.Value,
                     configuration.DistanceFactor.Value,
                     configuration.DistanceMoveUnableToMatch.Value,
                     configuration.DistancePixelDistanceTolerance.Value,
                     configuration.DistanceRenameToMatch.Value,
                     configuration.EyeThreshold.Value,
                     configuration.FaceAreaPermyriad.Value,
                     configuration.FaceConfidencePercent.Value,
                     configuration.FaceDistanceHiddenImageFactor.Value,
                     configuration.FaceDistancePermyriad.Value,
                     configuration.FocusDirectory,
                     configuration.FocusModel,
                     configuration.ForceFaceLastWriteTimeToCreationTime.Value,
                     configuration.ForceMetadataLastWriteTimeToCreationTime.Value,
                     configuration.ForceResizeLastWriteTimeToCreationTime.Value,
                     configuration.GenealogicalDataCommunicationFile,
                     configuration.IgnoreExtensions ?? Array.Empty<string>(),
                     configuration.JLinks ?? Array.Empty<string>(),
                     configuration.LoadOrCreateThenSaveDistanceResultsForOutputResolutions ?? Array.Empty<string>(),
                     configuration.LoadOrCreateThenSaveImageFacesResultsForOutputResolutions ?? Array.Empty<string>(),
                     configuration.LoadPhotoPrismLocations.Value,
                     configuration.LocationContainerDistanceTolerance,
                     configuration.LocationDigits.Value,
                     configuration.LocationFactor.Value,
                     configuration.LookForAbandoned.Value,
                     configuration.MappingDefaultName,
                     configuration.MappingUseDeterministicHashCodeUnknownFaceKeyValuePairsForAddToMapping.Value,
                     configuration.MappingUseDeterministicHashCodeUnknownFaceKeyValuePairsForSaveMapping.Value,
                     configuration.MixedYearRelativePaths ?? Array.Empty<string>(),
                     configuration.ModelDirectory,
                     configuration.ModelName,
                     configuration.OutputExtension,
                     configuration.OutputQuality.Value,
                     configuration.OutputResolutions ?? Array.Empty<string>(),
                     configuration.OverrideForFaceImages.Value,
                     configuration.OverrideForFaceLandmarkImages.Value,
                     configuration.OverrideForResizeImages.Value,
                     configuration.PersonBirthdayFirstYear.Value,
                     configuration.PersonBirthdayFormat,
                     configuration.PersonCharacters,
                     configuration.PersonCharactersCopyCount.Value,
                     configuration.PersonKeyFormat,
                     configuration.PredictorModelName,
                     configuration.PropertiesChangedForDistance.Value,
                     configuration.PropertiesChangedForFaces.Value,
                     configuration.PropertiesChangedForIndex.Value,
                     configuration.PropertiesChangedForMetadata.Value,
                     configuration.PropertiesChangedForResize.Value,
                     configuration.RadomUseBirthdayMinimum.Value,
                     configuration.RangeDaysDeltaTolerance ?? Array.Empty<int>(),
                     configuration.RangeDistanceTolerance ?? Array.Empty<float>(),
                     configuration.RangeFaceAreaTolerance ?? Array.Empty<float>(),
                     configuration.RangeFaceConfidence ?? Array.Empty<float>(),
                     configuration.RectangleIntersectMinimums ?? Array.Empty<float>(),
                     configuration.Reverse.Value,
                     configuration.SaveBlurHashForOutputResolutions ?? Array.Empty<string>(),
                     configuration.SaveFaceDistancesForOutputResolutions ?? Array.Empty<string>(),
                     configuration.SaveFaceLandmarkForOutputResolutions ?? Array.Empty<string>(),
                     configuration.SaveFilteredOriginalImagesFromJLinksForOutputResolutions ?? Array.Empty<string>(),
                     configuration.SaveIndividually.Value,
                     configuration.SaveFullYearOfRandomFiles.Value,
                     configuration.SaveMappedForOutputResolutions ?? Array.Empty<string>(),
                     configuration.SavePropertyShortcutsForOutputResolutions ?? Array.Empty<string>(),
                     configuration.SaveRandomForOutputResolutions ?? Array.Empty<string>(),
                     configuration.SaveResizedSubfiles.Value,
                     configuration.SaveShortcutsForOutputResolutions ?? Array.Empty<string>(),
                     configuration.SaveSortingWithoutPerson.Value,
                     configuration.SkipNotSkipDirectories ?? Array.Empty<string>(),
                     configuration.SkipOlderThanDays,
                     configuration.SkipPersonWithMoreThen,
                     configuration.SkipSearch.Value,
                     configuration.SortingMaximumPerFaceShouldBeHigh.Value,
                     configuration.SortingMaximumPerKey.Value,
                     configuration.SortingMinimumToUseSigma.Value,
                     configuration.TestDistanceResults.Value,
                     configuration.UseFilterTries.Value,
                     configuration.ValidKeyWordsToIgnoreInRandom ?? Array.Empty<string>(),
                     configuration.ValidResolutions ?? Array.Empty<string>());
        return result;
    }

    public static Models.Configuration Get(IsEnvironment isEnvironment, IConfigurationRoot configurationRoot, Property.Models.Configuration propertyConfiguration)
    {
        Models.Configuration result;
        Configuration? configuration;
        if (isEnvironment is null)
            configuration = configurationRoot.Get<Configuration>();
        else
        {
            string environmentName = IsEnvironment.GetEnvironmentName(isEnvironment);
            string section = string.Concat(environmentName, ":", nameof(Configuration));
            IConfigurationSection configurationSection = configurationRoot.GetSection(section);
            configuration = configurationSection.Get<Configuration>();
        }
        result = Get(configuration, propertyConfiguration);
        return result;
    }

}