namespace View_by_Distance.Shared.Models.Stateless.Methods;

internal abstract class Property
{

    internal static (int Season, string seasonName) GetSeason(int dayOfYear)
    {
        (int Season, string seasonName) result = dayOfYear switch
        {
            < 78 => new(0, "Winter"),
            < 124 => new(1, "Spring"),
            < 171 => new(2, "Spring"),
            < 217 => new(3, "Summer"),
            < 264 => new(4, "Summer"),
            < 309 => new(5, "Fall"),
            < 354 => new(6, "Fall"),
            _ => new(7, "Winter")
        };
        return result;
    }

    internal static (bool?, string[]) IsWrongYear(string[] segments, string year)
    {
        bool? result;
        string[] results = (
            from l
            in segments
            where l?.Length > 2
            && (
                l[..2] is "18" or "19" or "20"
            || (l.Length == 5 && l.Substring(1, 2) is "18" or "19" or "20" && (l[0] is '~' or '=' or '-' or '^' or '#'))
            || (l.Length == 6 && l[..2] is "18" or "19" or "20" && l[4] == '.')
            || (l.Length == 7 && l.Substring(1, 2) is "18" or "19" or "20" && l[5] == '.')
            )
            select l
        ).ToArray();
        string[] matches = (
            from l
            in results
            where l == year
            || (l.Length == 5 && l.Substring(1, 4) == year && (l[0] is '~' or '=' or '-' or '^' or '#'))
            || (l.Length == 6 && l[..4] == year && l[4] == '.')
            || (l.Length == 7 && l.Substring(1, 4) == year && l[5] == '.')
            select l
        ).ToArray();
        if (results.Length == 0)
            result = null;
        else
            result = matches.Length == 0;
        return new(result, results);
    }

    internal static (bool?, string[]) IsWrongYear(FilePath filePath, DateTime? dateTimeOriginal, List<DateTime> dateTimes)
    {
        string[] results = [];
        bool? result = null;
        string year;
        string directoryName;
        string[] directorySegments;
        List<DateTime> collection = [];
        string? check = Path.GetFullPath(filePath.FullName);
        string? pathRoot = Path.GetPathRoot(filePath.FullName);
        if (string.IsNullOrEmpty(pathRoot))
            throw new Exception();
        if (dateTimeOriginal is not null)
            collection.Add(dateTimeOriginal.Value);
        else
        {
            foreach (DateTime dateTime in dateTimes)
                collection.Add(dateTime);
        }
        foreach (DateTime dateTime in collection)
        {
            year = dateTime.ToString("yyyy");
            for (int i = 0; i < int.MaxValue; i++)
            {
                check = Path.GetDirectoryName(check);
                if (string.IsNullOrEmpty(check))
                    break;
                directoryName = Path.GetFileName(check);
                directorySegments = directoryName.Split(' ');
                (result, results) = IsWrongYear(directorySegments, year);
                if (result is not null)
                    break;
                if (check == pathRoot)
                    break;
            }
            if (result is not null && !result.Value)
                break;
        }
        return new(result, results);
    }

    internal static List<DateTime> GetDateTimes(DateTime creationTime, DateTime lastWriteTime, DateTime? dateTime, DateTime? dateTimeDigitized, DateTime? dateTimeFromName, DateTime? dateTimeOriginal, DateTime? gpsDateStamp)
    {
        List<DateTime> results =
        [
            creationTime,
            lastWriteTime
        ];
        if (dateTime.HasValue)
            results.Add(dateTime.Value);
        if (dateTimeDigitized.HasValue)
            results.Add(dateTimeDigitized.Value);
        if (dateTimeFromName.HasValue)
            results.Add(dateTimeFromName.Value);
        if (dateTimeOriginal.HasValue)
            results.Add(dateTimeOriginal.Value);
        if (gpsDateStamp.HasValue)
            results.Add(gpsDateStamp.Value);
        return results;
    }

    internal static DateTime GetDateTime(Models.Property? property)
    {
        DateTime result;
        if (property is null)
            result = DateTime.MinValue;
        else
        {
            List<DateTime> dateTimes =
            [
                property.CreationTime,
                property.LastWriteTime
            ];
            if (property.DateTime.HasValue)
                dateTimes.Add(property.DateTime.Value);
            if (property.DateTimeDigitized.HasValue)
                dateTimes.Add(property.DateTimeDigitized.Value);
            if (property.DateTimeFromName.HasValue)
                dateTimes.Add(property.DateTimeFromName.Value);
            if (property.DateTimeOriginal.HasValue)
                dateTimes.Add(property.DateTimeOriginal.Value);
            if (property.GPSDateStamp.HasValue)
                dateTimes.Add(property.GPSDateStamp.Value);
            result = dateTimes.Min();
        }
        return result;
    }

    internal static DateTime GetMinimumDateTime(Models.Property? property)
    {
        DateTime result;
        List<DateTime> dateTimes;
        if (property is null)
            result = DateTime.MinValue;
        else
        {
            dateTimes = IProperty.GetDateTimes(property);
            result = dateTimes.Min();
        }
        return result;
    }

    internal static string GetDiffRootDirectory(string diffPropertyDirectory)
    {
        string result = string.Empty;
        string results = "-Results";
        string? checkDirectory = diffPropertyDirectory;
        for (int i = 0; i < int.MaxValue; i++)
        {
            checkDirectory = Path.GetDirectoryName(checkDirectory);
            if (string.IsNullOrEmpty(checkDirectory))
                break;
            if (checkDirectory.EndsWith(results))
            {
                result = checkDirectory[..^results.Length];
                break;
            }
        }
        return result;
    }

}