using MetadataExtractor;
using MetadataExtractor.Formats.Avi;
using MetadataExtractor.Formats.Exif;
using MetadataExtractor.Formats.QuickTime;
using View_by_Distance.Shared.Models.Stateless;

namespace View_by_Distance.Metadata.Models.Stateless.Methods;

internal class Metadata
{

    internal static string? GetFaceEncoding(IReadOnlyList<MetadataExtractor.Directory> directories)
    {
        string? result;
        List<string> results = new();
        const string comment = "Comment: ";
        foreach (MetadataExtractor.Directory directory in directories)
        {
            if (directory.Name != "PNG-tEXt")
                continue;
            foreach (Tag tag in directory.Tags)
            {
                if (tag.Name != "Textual Data" || string.IsNullOrEmpty(tag.Description))
                    continue;
                if (!tag.Description.StartsWith(comment))
                    continue;
                results.Add(tag.Description);
            }
        }
        result = results.Any() ? results[0][comment.Length..] : null;
        return result;
    }

    internal static string? GetOutputResolution(IReadOnlyList<MetadataExtractor.Directory> directories)
    {
        string? result;
        List<string> results = new();
        const string artist = "Artist: ";
        foreach (MetadataExtractor.Directory directory in directories)
        {
            if (directory.Name != "PNG-tEXt")
                continue;
            foreach (Tag tag in directory.Tags)
            {
                if (tag.Name != "Textual Data" || string.IsNullOrEmpty(tag.Description))
                    continue;
                if (!tag.Description.StartsWith(artist))
                    continue;
                results.Add(tag.Description);
            }
        }
        result = results.Any() ? results[0][artist.Length..] : null;
        return result;
    }

    internal static DateTime GetMinimumDateTime(DateTime?[] dateTimes, int year, IReadOnlyList<MetadataExtractor.Directory> directories)
    {
        DateTime result;
        DateTime dateTime;
        List<DateTime> results = (from l in dateTimes where l is not null select l.Value).ToList();
        ExifDirectoryBase? exifDirectoryBase = directories.OfType<ExifDirectoryBase>().FirstOrDefault();
        if (exifDirectoryBase is not null)
        {
            if (exifDirectoryBase.TryGetDateTime(ExifDirectoryBase.TagDateTime, out dateTime))
                results.Add(dateTime);
            if (exifDirectoryBase.TryGetDateTime(ExifDirectoryBase.TagDateTimeDigitized, out dateTime))
                results.Add(dateTime);
            if (exifDirectoryBase.TryGetDateTime(ExifDirectoryBase.TagDateTimeOriginal, out dateTime))
                results.Add(dateTime);
        }
        AviDirectory? aviDirectory = directories.OfType<AviDirectory>().FirstOrDefault();
        if (aviDirectory is not null)
        {
            if (aviDirectory.TryGetDateTime(AviDirectory.TagDateTimeOriginal, out dateTime))
                results.Add(dateTime);
        }
        QuickTimeMovieHeaderDirectory? quickTimeMovieHeaderDirectory = directories.OfType<QuickTimeMovieHeaderDirectory>().FirstOrDefault();
        if (quickTimeMovieHeaderDirectory is not null)
        {
            if (quickTimeMovieHeaderDirectory.TryGetDateTime(QuickTimeMovieHeaderDirectory.TagCreated, out dateTime))
                results.Add(dateTime);
        }
        QuickTimeTrackHeaderDirectory? quickTimeTrackHeaderDirectory = directories.OfType<QuickTimeTrackHeaderDirectory>().FirstOrDefault();
        if (quickTimeTrackHeaderDirectory is not null)
        {
            if (quickTimeTrackHeaderDirectory.TryGetDateTime(QuickTimeTrackHeaderDirectory.TagCreated, out dateTime))
                results.Add(dateTime);
        }
        DateTime[] filtered = (from l in results where l.Year >= year select l).ToArray();
        if (!filtered.Any())
            result = results.Min();
        else
            result = filtered.Min();
        return result;
    }

    internal static string? GetModel(IReadOnlyList<MetadataExtractor.Directory> directories)
    {
        string? result;
        ExifDirectoryBase? exifDirectoryBase = directories.OfType<ExifDirectoryBase>().FirstOrDefault();
        if (exifDirectoryBase is null)
            result = null;
        else
            result = exifDirectoryBase.GetString(ExifDirectoryBase.TagModel);
        return result;
    }

    internal static int GetOrientation(List<KeyValuePair<string, string>> metadataCollection)
    {
        int result;
        const string orientation = nameof(IExif.Tags.Orientation);
        List<string> orientations = (from l in metadataCollection where l.Key.Contains(orientation) select l.Value).ToList();
        if (!orientations.Any())
            result = 0;
        else if (!int.TryParse(orientations[0], out result))
            result = 0;
        return result;
    }

}