using System;
using System.Collections.Generic;
using System.Globalization;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;

namespace VarTitolo
{


    public partial class JsonVarTitolo
    {
        [JsonProperty("errors")]
        public Error[][] Errors { get; set; }

        [JsonProperty("results")]
        public Result[] Results { get; set; }
    }

    public partial class Result
    {
        [JsonProperty("var")]
        //public object Var { get; set; }
        public double? Var { get; set; }

        [JsonProperty("percentile")]
        public double Percentile { get; set; }

        [JsonProperty("frequency")]
        public long Frequency { get; set; }

        [JsonProperty("horizon")]
        public long Horizon { get; set; }

        [JsonProperty("lookback_days")]
        public long LookbackDays { get; set; }
    }

    public partial struct Error
    {
        public long? Integer;
        public string String;
        public string[] StringArray;

        public bool IsNull => StringArray == null && Integer == null && String == null;
    }

    public partial class JsonVarTitolo
    {
        public static JsonVarTitolo FromJson(string json) => JsonConvert.DeserializeObject<JsonVarTitolo>(json, Converter.Settings);
    }

    public static class Serialize
    {
        public static string ToJson(this JsonVarTitolo self) => JsonConvert.SerializeObject(self, Converter.Settings);
    }

    internal static class Converter
    {
        public static readonly JsonSerializerSettings Settings = new JsonSerializerSettings
        {
            MetadataPropertyHandling = MetadataPropertyHandling.Ignore,
            DateParseHandling = DateParseHandling.None,
            Converters = {
                ErrorConverter.Singleton,
                new IsoDateTimeConverter { DateTimeStyles = DateTimeStyles.AssumeUniversal }
            },
        };
    }

    internal class ErrorConverter : JsonConverter
    {
        public override bool CanConvert(Type t) => t == typeof(Error) || t == typeof(Error?);

        public override object ReadJson(JsonReader reader, Type t, object existingValue, JsonSerializer serializer)
        {
            switch (reader.TokenType)
            {
                case JsonToken.Integer:
                    var integerValue = serializer.Deserialize<long>(reader);
                    return new Error { Integer = integerValue };
                case JsonToken.String:
                case JsonToken.Date:
                    var stringValue = serializer.Deserialize<string>(reader);
                    return new Error { String = stringValue };
                case JsonToken.StartArray:
                    var arrayValue = serializer.Deserialize<string[]>(reader);
                    return new Error { StringArray = arrayValue };
            }
            throw new Exception("Cannot unmarshal type Error");
        }

        public override void WriteJson(JsonWriter writer, object untypedValue, JsonSerializer serializer)
        {
            var value = (Error)untypedValue;
            if (value.Integer != null)
            {
                serializer.Serialize(writer, value.Integer.Value);
                return;
            }
            if (value.String != null)
            {
                serializer.Serialize(writer, value.String);
                return;
            }
            if (value.StringArray != null)
            {
                serializer.Serialize(writer, value.StringArray);
                return;
            }
            throw new Exception("Cannot marshal type Error");
        }

        public static readonly ErrorConverter Singleton = new ErrorConverter();
    }
}
