using System.Text.Json;

namespace Dacryptero.Search.Sorting
{
    public struct SortInfoEntry
    {
        public string? Name { get; }

        public string? StringValue { get; }

        public double? DoubleValue { get; }

        public SortInfoEntry(string name, string value, bool truncate = true)
        {
            Name = name;
            StringValue = value.Length < 16 || !truncate ? value : value.Substring(0, 16);
            DoubleValue = null;
        }

        public SortInfoEntry(string name, double value)
        {
            Name = name;
            StringValue = null;
            DoubleValue = value;
        }

        public static SortInfoEntry FromDbValue(string name, LiteDB.BsonValue value)
        {
            switch (value.Type)
            {
                case LiteDB.BsonType.Int32:
                    return new SortInfoEntry(name, value.AsInt32);
                case LiteDB.BsonType.Int64:
                    return new SortInfoEntry(name, value.AsInt64);
                case LiteDB.BsonType.Double:
                    return new SortInfoEntry(name, value.AsDouble);
                case LiteDB.BsonType.Decimal:
                    return new SortInfoEntry(name, (double)value.AsDecimal);
                case LiteDB.BsonType.String:
                    return new SortInfoEntry(name, value.AsString);
                case LiteDB.BsonType.Binary:
                    return new SortInfoEntry(name, System.Convert.ToHexString(value.AsBinary));
                case LiteDB.BsonType.ObjectId:
                    return new SortInfoEntry(name, value.AsObjectId.ToString(), false);
                case LiteDB.BsonType.Guid:
                    return new SortInfoEntry(name, value.AsGuid.ToString(), false);
                case LiteDB.BsonType.Boolean:
                    return new SortInfoEntry(name, value.AsBoolean ? 1 : 0);
                case LiteDB.BsonType.DateTime:
                    return new SortInfoEntry(name, value.AsDateTime.ToFileTimeUtc());
                default: 
                    Serilog.Log.Information("Cannot create sorting for {name} as {type}: {value}", name, value.Type, value);
                    return new SortInfoEntry(); // this type is not sortable
            }
        }

        public void WriteTo(Utf8JsonWriter writer)
        {
            if (StringValue is not null)
            {
                writer.WriteStringValue(StringValue);
            }
            else if (DoubleValue is not null)
            {
                writer.WriteNumberValue(DoubleValue.Value);
            }
            else
            {
                writer.WriteNullValue();
            }
        }
    }
}