using AutoMapper;
using DigitalData.Core.Security.Config;
using Microsoft.IdentityModel.Tokens;
namespace DigitalData.Core.Security
{
internal static class Extension
{
internal static string ToBase64String(this byte[] bytes) => Convert.ToBase64String(bytes);
internal static byte[] Base64ToByte(this string base64String) => Convert.FromBase64String(base64String);
internal static byte[] ToBytes(this string str) => System.Text.Encoding.UTF8.GetBytes(str);
internal static string BytesToString(this byte[] bytes) => System.Text.Encoding.UTF8.GetString(bytes);
///
/// Converts a to a formatted string based on the specified format string.
///
/// - If the format contains the symbol “//”, the method divides the numeric value obtained from the left side of the format
/// by one minus the numeric value obtained from the right side of the format string and adds one. For instance:
///
/// - If the date is 02.03.2024 and the format is "MM//2", it extracts the month (02), subtracts one (3), divides it by 2,
/// rounds down the outgoing number (1), adds one to the number (resulting in 2).
///
/// - If the format does not contain "//", the method uses the default format.
///
///
/// The value to be formatted.
/// The format string that dictates the formatting of the date. If the format includes the "//" symbol,
/// it splits the string at "//" and divides the left-side value by the right-side value. The format string can include standard
/// format patterns.
/// A string representation of the formatted date, or the result of the division operation if "//" is present in the format.
/// Thrown if the format string is invalid, such as having an incorrect number of parts after "//".
/// Thrown if the right side of the "//" contains a zero, resulting in division by zero.
/// Thrown if either the left-side or right-side value of "//" cannot be parsed as an integer.
internal static string ToTag(this DateTime date, string format)
{
if (format is not null && format.Contains("//"))
{
var subStrings = format.Split("//");
if (subStrings.Length != 2)
throw new ArgumentException($"Date tag format {format} is invalid. It must contain exactly one '//' separator.", nameof(format));
var formattedLeft = date.ToString(subStrings[0]);
if (!int.TryParse(formattedLeft, out var dateValue))
throw new FormatException($"The left-side value ({formattedLeft}) of the format could not be parsed to an integer.");
if (!int.TryParse(subStrings[1], out var divisor))
throw new FormatException($"The right-side value ({divisor}) of the format could not be parsed to an integer.");
if (divisor == 0)
throw new DivideByZeroException($"Date tag format {format} includes division by zero, which is not allowed.");
var result = (dateValue - 1) / divisor + 1;
return result.ToString();
}
return date.ToString(format);
}
///
/// Converts a to a formatted string based on the specified format string.
///
/// - If the format contains the symbol “//”, the method divides the numeric value obtained from the left side of the format
/// by one minus the numeric value obtained from the right side of the format string and adds one. For instance:
///
/// - If the date is 02.03.2024 and the format is "MM//2", it extracts the month (02), subtracts one (3), divides it by 2,
/// rounds down the outgoing number (1), adds one to the number (resulting in 2).
///
/// - If the format does not contain "//", the method uses the default format.
///
/// This method provides a way to format the date based on typical or customized rules, including mathematical operations like division.
///
/// The value to be formatted. It will convert to DateTime to use the method shared with DateTime.
/// The format string that dictates the formatting of the date. If the format includes the "//" symbol,
/// it splits the string at "//" and divides the left-side value by the right-side value. The format string can include standard
/// format patterns.
/// A string representation of the formatted date, or the result of the division operation if "//" is present in the format.
/// Thrown if the format string is invalid, such as having an incorrect number of parts after "//".
/// Thrown if the right side of the "//" contains a zero, resulting in division by zero.
/// Thrown if either the left-side or right-side value of "//" cannot be parsed as an integer.
internal static string ToTag(this DateOnly date, string format) => date.ToDateTime(new()).ToTag(format);
///
/// Maps a to a .
///
/// The instance used for mapping.
/// The instance to be mapped.
/// A instance populated with the mapped values.
/// Thrown if or is null.
internal static SecurityTokenDescriptor Map(this IMapper mapper, TokenDescription description)
=> mapper.Map(description, new SecurityTokenDescriptor());
}
}