using System.Text; namespace Phares.Shared.Models.Stateless; internal abstract class Id { internal static int GetDeterministicHashCode(byte[] value) { int result; unchecked { int hash1 = (5381 << 16) + 5381; int hash2 = hash1; for (int i = 0; i < value.Length; i += 2) { hash1 = ((hash1 << 5) + hash1) ^ value[i]; if (i == value.Length - 1) break; hash2 = ((hash2 << 5) + hash2) ^ value[i + 1]; } result = hash1 + (hash2 * 1566083941); } return result; } internal static byte GetHasIgnoreKeyword(FilePath filePath) => (byte)(filePath.Id > -1 ? 8 : 2); internal static byte GetHasDateTimeOriginal(ResultSettings resultSettings, FilePath filePath) => (byte)(IsIgnoreOrValidVideoFormatExtension(resultSettings, filePath) ? filePath.Id > -1 ? 6 : 4 : filePath.Id > -1 ? 9 : 1); private static string GetExtension(string nameWithoutExtension, string extensionLowered) => extensionLowered is not ".xmp" and not ".json" ? extensionLowered : Path.GetExtension(nameWithoutExtension); private static string GetExtension(FilePath filePath) => GetExtension(filePath.NameWithoutExtension, filePath.ExtensionLowered); private static bool IsIgnoreOrValidVideoFormatExtension(ResultSettings resultSettings, FilePath filePath) => IsIgnoreOrValidVideoFormatExtension(resultSettings, GetExtension(filePath)); private static bool IsIgnoreOrValidVideoFormatExtension(ResultSettings resultSettings, string extensionLowered) => resultSettings.IgnoreExtensions.Contains(extensionLowered) || resultSettings.ValidVideoFormatExtensions.Contains(extensionLowered); internal static byte GetMissingDateTimeOriginal(ResultSettings resultSettings, FilePath filePath) => (byte)(IsIgnoreOrValidVideoFormatExtension(resultSettings, filePath) ? filePath.Id > -1 ? 5 : 0 : filePath.Id > -1 ? 7 : 3); internal static int GetId(ResultSettings resultSettings, MetadataSettings metadataSettings, string intelligentId) { int result; StringBuilder results = new(); if (metadataSettings.IntMinValueLength < (resultSettings.ResultAllInOneSubdirectoryLength + 2)) throw new NotSupportedException(); for (int i = intelligentId.Length - (resultSettings.ResultAllInOneSubdirectoryLength + 2); i > -1; i--) _ = results.Append(intelligentId[i]); _ = results.Append(intelligentId[^3]).Append(intelligentId[^2]); result = int.Parse(results.ToString()); if (intelligentId[^1] is '0' or '1' or '2' or '3' or '4') result *= -1; else if (intelligentId[^1] is not '9' and not '8' and not '7' and not '6' and not '5') throw new NotSupportedException(); return result; } internal static bool NameWithoutExtensionIsIdFormat(MetadataSettings metadataSettings, string fileNameFirstSegment) { bool result; if (fileNameFirstSegment.Length < 5 || fileNameFirstSegment.Length > metadataSettings.IntMinValueLength) result = false; else { bool skipOneAllAreNumbers = fileNameFirstSegment[1..].All(char.IsNumber); result = (skipOneAllAreNumbers && fileNameFirstSegment[0] == '-') || (skipOneAllAreNumbers && char.IsNumber(fileNameFirstSegment[0])); } return result; } private static string GetIntelligentId(ResultSettings resultSettings, MetadataSettings metadataSettings, long id, string nameWithoutExtension, string extensionLowered, bool? hasIgnoreKeyword, bool? hasDateTimeOriginal) { string result; StringBuilder stringBuilder = new(); if (metadataSettings.IntMinValueLength < (resultSettings.ResultAllInOneSubdirectoryLength + 2)) throw new NotSupportedException(); int key; string value; List resultAllInOneSubdirectoryChars = []; if (hasDateTimeOriginal is null) { key = 0; value = id.ToString().PadLeft(metadataSettings.IntMinValueLength, '0'); } else if (id > -1) { string checkExtension = GetExtension(nameWithoutExtension, extensionLowered); if (IsIgnoreOrValidVideoFormatExtension(resultSettings, checkExtension)) key = hasIgnoreKeyword is not null && hasIgnoreKeyword.Value ? throw new NotImplementedException() : hasDateTimeOriginal.Value ? 6 : 5; else key = hasIgnoreKeyword is not null && hasIgnoreKeyword.Value ? 8 : hasDateTimeOriginal.Value ? 9 : 7; value = id.ToString().PadLeft(metadataSettings.IntMinValueLength, '0'); } else { string checkExtension = GetExtension(nameWithoutExtension, extensionLowered); if (IsIgnoreOrValidVideoFormatExtension(resultSettings, checkExtension)) key = hasIgnoreKeyword is not null && hasIgnoreKeyword.Value ? throw new NotImplementedException() : hasDateTimeOriginal.Value ? 4 : 0; else key = hasIgnoreKeyword is not null && hasIgnoreKeyword.Value ? 2 : hasDateTimeOriginal.Value ? 1 : 3; value = id.ToString()[1..].PadLeft(metadataSettings.IntMinValueLength, '0'); } for (int i = value.Length - resultSettings.ResultAllInOneSubdirectoryLength - 1; i > -1; i--) _ = stringBuilder.Append(value[i]); for (int i = value.Length - resultSettings.ResultAllInOneSubdirectoryLength; i < value.Length; i++) resultAllInOneSubdirectoryChars.Add(value[i]); result = $"{stringBuilder}{string.Join(string.Empty, resultAllInOneSubdirectoryChars)}{key}"; return result; } private static string GetIntelligentId(ResultSettings resultSettings, MetadataSettings metadataSettings, FilePath filePath) => filePath.Id is null ? throw new Exception() : GetIntelligentId(resultSettings, metadataSettings, filePath.Id.Value, filePath.NameWithoutExtension, filePath.ExtensionLowered, filePath.HasIgnoreKeyword, filePath.HasDateTimeOriginal); internal static string GetPaddedId(ResultSettings resultSettings, MetadataSettings metadataSettings, int id, string nameWithoutExtension, string extensionLowered, bool? hasIgnoreKeyword, bool? hasDateTimeOriginal, int? index) { string result; if (metadataSettings.Offset < 0) result = Guid.NewGuid().ToString(); else { string intelligentId = GetIntelligentId(resultSettings, metadataSettings, id, nameWithoutExtension, extensionLowered, hasIgnoreKeyword, hasDateTimeOriginal); int check = GetId(resultSettings, metadataSettings, intelligentId); if (check != id) throw new NotSupportedException(); result = index is null || metadataSettings.Offset == IId.DeterministicHashCode ? intelligentId : $"{metadataSettings.Offset + index}{intelligentId}"; } return result; } internal static string GetPaddedId(ResultSettings resultSettings, MetadataSettings metadataSettings, FilePath filePath, int? index) { string result; if (metadataSettings.Offset < 0) result = Guid.NewGuid().ToString(); else { string intelligentId = GetIntelligentId(resultSettings, metadataSettings, filePath); int check = GetId(resultSettings, metadataSettings, intelligentId); if (filePath.Id is not null && check != filePath.Id.Value) throw new NotSupportedException(); result = index is null || metadataSettings.Offset == IId.DeterministicHashCode ? intelligentId : $"{metadataSettings.Offset + index}{intelligentId}"; } return result; } }