using System.Collections.ObjectModel;
using View_by_Distance.Shared.Models;
using View_by_Distance.Shared.Models.Properties;
using View_by_Distance.Shared.Models.Stateless;

namespace View_by_Distance.Metadata.Models.Stateless;

internal static class Get
{

    internal static ReadOnlyDictionary<string, List<FileHolder>> GetKeyValuePairs(IEnumerable<string> files)
    {
        Dictionary<string, List<FileHolder>> results = [];
        string key;
        FileHolder fileHolder;
        List<FileHolder>? fileHolders;
        foreach (string file in files)
        {
            fileHolder = FileHolder.Get(file);
            if (fileHolder.DirectoryFullPath is null)
                continue;
            key = $"{Path.Combine(fileHolder.DirectoryFullPath, fileHolder.NameWithoutExtension)}";
            if (!results.TryGetValue(key, out fileHolders))
            {
                results.Add(key, []);
                if (!results.TryGetValue(key, out fileHolders))
                    throw new NotImplementedException();
            }
            fileHolders.Add(fileHolder);
        }
        return results.AsReadOnly();
    }

    internal static ReadOnlyDictionary<string, List<FileHolder>> GetKeyValuePairs(IEnumerable<NginxFileSystem> collection)
    {
        Dictionary<string, List<FileHolder>> results = [];
        string key;
        FileHolder fileHolder;
        List<FileHolder>? fileHolders;
        foreach (NginxFileSystem nginxFileSystem in collection)
        {
            fileHolder = FileHolder.Get(nginxFileSystem);
            if (fileHolder.DirectoryFullPath is null)
                continue;
            key = $"{Path.Combine(fileHolder.DirectoryFullPath, fileHolder.NameWithoutExtension)}";
            if (!results.TryGetValue(key, out fileHolders))
            {
                results.Add(key, []);
                if (!results.TryGetValue(key, out fileHolders))
                    throw new NotImplementedException();
            }
            fileHolders.Add(fileHolder);
        }
        return results.AsReadOnly();
    }

    internal static Action<string> SetExifDirectoryCollection(IRename rename, ResultSettings resultSettings, MetadataSettings metadataSettings, IRenameSettings renameSettings, A_Metadata metadata, List<string> distinct, List<MetadataGroup> metadataGroups)
    {
        return file =>
        {
            rename.Tick();
            ExifDirectory exifDirectory;
            MetadataGroup metadataGroup;
            DeterministicHashCode deterministicHashCode;
            FileHolder fileHolder = FileHolder.Get(file);
            bool fastForwardMovingPictureExpertsGroupUsed;
            MinimumYearAndPathCombined minimumYearAndPathCombined;
            FilePath? fastForwardMovingPictureExpertsGroupFilePath;
            ReadOnlyCollection<string>? fastForwardMovingPictureExpertsGroupFiles;
            FilePath filePath = FilePath.Get(resultSettings, metadataSettings, fileHolder, index: null);
            string key = $"{Path.Combine(fileHolder.DirectoryFullPath ?? throw new NotSupportedException(), fileHolder.NameWithoutExtension)}";
            if (distinct.Contains(key))
                throw new NotSupportedException("Turn off parallelism when sidecar files are present!");
            if (renameSettings.SkipIdFiles && filePath.Id is not null && (filePath.IsIntelligentIdFormat || filePath.SortOrder is null))
                return;
            if (filePath.Id is not null)
            {
                fastForwardMovingPictureExpertsGroupFiles = null;
                deterministicHashCode = new(null, filePath.Id, null);
            }
            else
            {
                fastForwardMovingPictureExpertsGroupFiles = rename.ConvertAndGetFastForwardMovingPictureExpertsGroupFiles(renameSettings, filePath);
                fastForwardMovingPictureExpertsGroupFilePath = fastForwardMovingPictureExpertsGroupFiles.Count == 0 ? null : FilePath.Get(resultSettings, metadataSettings, FileHolder.Get(fastForwardMovingPictureExpertsGroupFiles[0]), index: null);
                deterministicHashCode = fastForwardMovingPictureExpertsGroupFilePath is null ? rename.GetDeterministicHashCode(filePath) : rename.GetDeterministicHashCode(fastForwardMovingPictureExpertsGroupFilePath);
            }
            filePath = FilePath.Get(filePath, deterministicHashCode);
            fastForwardMovingPictureExpertsGroupUsed = fastForwardMovingPictureExpertsGroupFiles is not null && fastForwardMovingPictureExpertsGroupFiles.Count > 0;
            (minimumYearAndPathCombined, exifDirectory) = metadata.GetMetadataCollection(resultSettings, metadataSettings, filePath);
            metadataGroup = new(fastForwardMovingPictureExpertsGroupUsed, filePath, minimumYearAndPathCombined, exifDirectory, new([]));
            lock (metadataGroups)
                metadataGroups.Add(metadataGroup);
            if (fastForwardMovingPictureExpertsGroupUsed && fastForwardMovingPictureExpertsGroupFiles is not null)
            {
                foreach (string fastForwardMovingPictureExpertsGroupFile in fastForwardMovingPictureExpertsGroupFiles)
                    File.Delete(fastForwardMovingPictureExpertsGroupFile);
            }
        };
    }

    internal static Action<string> SetExifDirectoryCollection(IWindows windows, ResultSettings resultSettings, MetadataSettings metadataSettings, IWindowsSettings windowsSettings, A_Metadata metadata, List<string> distinct, List<MetadataGroup> metadataGroups)
    {
        return file =>
        {
            windows.Tick();
            ExifDirectory exifDirectory;
            MetadataGroup metadataGroup;
            HttpClient? httpClient = null;
            DeterministicHashCode deterministicHashCode;
            FileHolder fileHolder = FileHolder.Get(file);
            MinimumYearAndPathCombined minimumYearAndPathCombined;
            bool fastForwardMovingPictureExpertsGroupUsed;
            FilePath? fastForwardMovingPictureExpertsGroupFilePath;
            ReadOnlyCollection<string>? fastForwardMovingPictureExpertsGroupFiles;
            FilePath filePath = FilePath.Get(resultSettings, metadataSettings, fileHolder, index: null);
            string key = $"{Path.Combine(fileHolder.DirectoryFullPath ?? throw new NotSupportedException(), fileHolder.NameWithoutExtension)}";
            if (distinct.Contains(key))
                throw new NotSupportedException("Turn off parallelism when sidecar files are present!");
            if (filePath.Id is null || (!filePath.IsIntelligentIdFormat && filePath.SortOrder is not null))
            {
                if (filePath.Id is not null)
                {
                    fastForwardMovingPictureExpertsGroupFiles = null;
                    deterministicHashCode = new(null, filePath.Id, null);
                }
                else
                {
                    fastForwardMovingPictureExpertsGroupFiles = windows.ConvertAndGetFastForwardMovingPictureExpertsGroupFiles(windowsSettings, httpClient, filePath);
                    fastForwardMovingPictureExpertsGroupFilePath = fastForwardMovingPictureExpertsGroupFiles.Count == 0 ? null : FilePath.Get(resultSettings, metadataSettings, FileHolder.Get(fastForwardMovingPictureExpertsGroupFiles[0]), index: null);
                    deterministicHashCode = fastForwardMovingPictureExpertsGroupFilePath is null ? windows.GetDeterministicHashCode(httpClient, filePath) : windows.GetDeterministicHashCode(httpClient, fastForwardMovingPictureExpertsGroupFilePath);
                }
                filePath = FilePath.Get(filePath, deterministicHashCode);
                fastForwardMovingPictureExpertsGroupUsed = fastForwardMovingPictureExpertsGroupFiles is not null && fastForwardMovingPictureExpertsGroupFiles.Count > 0;
                (minimumYearAndPathCombined, exifDirectory) = metadata.GetMetadataCollection(resultSettings, metadataSettings, filePath);
                metadataGroup = new(fastForwardMovingPictureExpertsGroupUsed, filePath, minimumYearAndPathCombined, exifDirectory, new([]));
                lock (metadataGroups)
                    metadataGroups.Add(metadataGroup);
                if (fastForwardMovingPictureExpertsGroupUsed && fastForwardMovingPictureExpertsGroupFiles is not null)
                {
                    foreach (string fastForwardMovingPictureExpertsGroupFile in fastForwardMovingPictureExpertsGroupFiles)
                        File.Delete(fastForwardMovingPictureExpertsGroupFile);
                }
            }

        };
    }

}