ModelSerializationExtensions
using Azure.Core;
using System;
using System.ClientModel.Primitives;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.Runtime.CompilerServices;
using System.Text.Json;
using System.Xml;
namespace Azure.Storage.Common
{
    internal static class ModelSerializationExtensions
    {
        internal static class TypeFormatters
        {
            private const string RoundtripZFormat = "yyyy-MM-ddTHH:mm:ss.fffffffZ";
            public const string DefaultNumberFormat = "G";
            public static string ToString(bool value)
            {
                if (!value)
                    return "false";
                return "true";
            }
            public static string ToString(DateTime value, string format)
            {
                if (value.Kind != DateTimeKind.Utc) {
                    DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(143, 2);
                    defaultInterpolatedStringHandler.AppendLiteral("DateTime ");
                    defaultInterpolatedStringHandler.AppendFormatted(value);
                    defaultInterpolatedStringHandler.AppendLiteral(" has a Kind of ");
                    defaultInterpolatedStringHandler.AppendFormatted(value.Kind);
                    defaultInterpolatedStringHandler.AppendLiteral(". Azure SDK requires it to be UTC. You can call DateTime.SpecifyKind to change Kind property value to DateTimeKind.Utc.");
                    throw new NotSupportedException(defaultInterpolatedStringHandler.ToStringAndClear());
                }
                return ToString((DateTimeOffset)value, format);
            }
            public static string ToString(DateTimeOffset value, string format)
            {
                if (format == "D")
                    return value.ToString("yyyy-MM-dd", CultureInfo.InvariantCulture);
                if (format == "U")
                    return value.ToUnixTimeSeconds().ToString(CultureInfo.InvariantCulture);
                DateTimeOffset dateTimeOffset;
                if (format == "O") {
                    dateTimeOffset = value.ToUniversalTime();
                    return dateTimeOffset.ToString("yyyy-MM-ddTHH:mm:ss.fffffffZ", CultureInfo.InvariantCulture);
                }
                if (format == "o") {
                    dateTimeOffset = value.ToUniversalTime();
                    return dateTimeOffset.ToString("yyyy-MM-ddTHH:mm:ss.fffffffZ", CultureInfo.InvariantCulture);
                }
                if (format == "R")
                    return value.ToString("r", CultureInfo.InvariantCulture);
                return value.ToString(format, CultureInfo.InvariantCulture);
            }
            public static string ToString(TimeSpan value, string format)
            {
                if (!(format == "P"))
                    return value.ToString(format, CultureInfo.InvariantCulture);
                return XmlConvert.ToString(value);
            }
            public static string ToString(byte[] value, string format)
            {
                if (format == "U")
                    return ToBase64UrlString(value);
                if (!(format == "D"))
                    throw new ArgumentException("Format is not supported: '" + format + "'", "format");
                return Convert.ToBase64String(value);
            }
            public static string ToBase64UrlString(byte[] value)
            {
                char[] array;
                int num;
                int num2;
                checked {
                    array = new char[unchecked(checked(value.Length + 2) / 3) * 4];
                    num = Convert.ToBase64CharArray(value, 0, value.Length, array, 0);
                    num2 = 0;
                }
                while (true) {
                    if (num2 < num) {
                        switch (array[num2]) {
                        case '+':
                            array[num2] = '-';
                            goto default;
                        case '/':
                            array[num2] = '_';
                            goto default;
                        default:
                            num2++;
                            continue;
                        case '=':
                            break;
                        }
                    }
                    break;
                }
                return new string(array, 0, num2);
            }
            public static byte[] FromBase64UrlString(string value)
            {
                int num;
                switch (value.Length % 4) {
                case 0:
                    num = 0;
                    break;
                case 2:
                    num = 2;
                    break;
                case 3:
                    num = 1;
                    break;
                default:
                    throw new InvalidOperationException("Malformed input");
                }
                int num2 = num;
                char[] array = new char[value.Length + num2];
                int i;
                for (i = 0; i < value.Length; i++) {
                    char c = value[i];
                    switch (c) {
                    case '-':
                        array[i] = '+';
                        break;
                    case '_':
                        array[i] = '/';
                        break;
                    default:
                        array[i] = c;
                        break;
                    }
                }
                for (; i < array.Length; i++) {
                    array[i] = '=';
                }
                return Convert.FromBase64CharArray(array, 0, array.Length);
            }
            public static DateTimeOffset ParseDateTimeOffset(string value, string format)
            {
                if (!(format == "U"))
                    return DateTimeOffset.Parse(value, CultureInfo.InvariantCulture, DateTimeStyles.AssumeUniversal);
                return DateTimeOffset.FromUnixTimeSeconds(long.Parse(value, CultureInfo.InvariantCulture));
            }
            public static TimeSpan ParseTimeSpan(string value, string format)
            {
                if (!(format == "P"))
                    return TimeSpan.ParseExact(value, format, CultureInfo.InvariantCulture);
                return XmlConvert.ToTimeSpan(value);
            }
            public static string ConvertToString(object value, string format = null)
            {
                if (value == null)
                    return "null";
                string text = value as string;
                if (text != null)
                    return text;
                if (!(value is bool)) {
                    if (!(value is int) && !(value is float) && !(value is double) && !(value is long) && !(value is decimal)) {
                        byte[] array = value as byte[];
                        if (array == null) {
                            IEnumerable<string> enumerable = value as IEnumerable<string>;
                            if (enumerable != null)
                                return string.Join(",", enumerable);
                            if (value is DateTimeOffset) {
                                DateTimeOffset value2 = (DateTimeOffset)value;
                                if (format != null)
                                    return ToString(value2, format);
                            } else {
                                if (value is TimeSpan) {
                                    TimeSpan value3 = (TimeSpan)value;
                                    if (format == null)
                                        return XmlConvert.ToString(value3);
                                    return ToString(value3, format);
                                }
                                if (value is Guid)
                                    return ((Guid)value).ToString();
                                BinaryData val = value as BinaryData;
                                if (val != null)
                                    return ConvertToString(val.ToArray(), format);
                            }
                        } else if (format != null) {
                            return ToString(array, format);
                        }
                        return value.ToString();
                    }
                    return ((IFormattable)value).ToString("G", CultureInfo.InvariantCulture);
                }
                bool value4 = (bool)value;
                return ToString(value4);
            }
        }
        internal static readonly ModelReaderWriterOptions WireOptions = new ModelReaderWriterOptions("W");
        public static object GetObject(this JsonElement element)
        {
            switch (element.ValueKind) {
            case JsonValueKind.String:
                return element.GetString();
            case JsonValueKind.Number:
                if (element.TryGetInt32(out int value))
                    return value;
                if (element.TryGetInt64(out long value2))
                    return value2;
                return element.GetDouble();
            case JsonValueKind.True:
                return true;
            case JsonValueKind.False:
                return false;
            case JsonValueKind.Undefined:
            case JsonValueKind.Null:
                return null;
            case JsonValueKind.Object: {
                Dictionary<string, object> dictionary = new Dictionary<string, object>();
                {
                    foreach (JsonProperty item in element.EnumerateObject()) {
                        dictionary.Add(item.Name, item.Value.GetObject());
                    }
                    return dictionary;
                }
            }
            case JsonValueKind.Array: {
                List<object> list = new List<object>();
                foreach (JsonElement item2 in element.EnumerateArray()) {
                    list.Add(item2.GetObject());
                }
                return list.ToArray();
            }
            default: {
                DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(25, 1);
                defaultInterpolatedStringHandler.AppendLiteral("Not supported value kind ");
                defaultInterpolatedStringHandler.AppendFormatted(element.ValueKind);
                throw new NotSupportedException(defaultInterpolatedStringHandler.ToStringAndClear());
            }
            }
        }
        public static byte[] GetBytesFromBase64(this JsonElement element, string format)
        {
            if (element.ValueKind == JsonValueKind.Null)
                return null;
            if (format == "U")
                return TypeFormatters.FromBase64UrlString(element.GetRequiredString());
            if (!(format == "D"))
                throw new ArgumentException("Format is not supported: '" + format + "'", "format");
            return element.GetBytesFromBase64();
        }
        public static DateTimeOffset GetDateTimeOffset(this JsonElement element, string format)
        {
            if (format == "U" && element.ValueKind == JsonValueKind.Number)
                return DateTimeOffset.FromUnixTimeSeconds(element.GetInt64());
            return TypeFormatters.ParseDateTimeOffset(element.GetString(), format);
        }
        public static TimeSpan GetTimeSpan(this JsonElement element, string format)
        {
            return TypeFormatters.ParseTimeSpan(element.GetString(), format);
        }
        public static char GetChar(this JsonElement element)
        {
            if (element.ValueKind == JsonValueKind.String) {
                string string = element.GetString();
                if (string == null || string.Length != 1)
                    throw new NotSupportedException("Cannot convert \"" + string + "\" to a char");
                return string[0];
            }
            DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(25, 1);
            defaultInterpolatedStringHandler.AppendLiteral("Cannot convert ");
            defaultInterpolatedStringHandler.AppendFormatted(element.ValueKind);
            defaultInterpolatedStringHandler.AppendLiteral(" to a char");
            throw new NotSupportedException(defaultInterpolatedStringHandler.ToStringAndClear());
        }
        [Conditional("DEBUG")]
        public static void ThrowNonNullablePropertyIsNull(this JsonProperty property)
        {
            throw new JsonException("A property '" + property.Name + "' defined as non-nullable but received as null from the service. This exception only happens in DEBUG builds of the library and would be ignored in the release build");
        }
        public static string GetRequiredString(this JsonElement element)
        {
            string string = element.GetString();
            if (string == null) {
                DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(97, 1);
                defaultInterpolatedStringHandler.AppendLiteral("The requested operation requires an element of type 'String', but the target element has type '");
                defaultInterpolatedStringHandler.AppendFormatted(element.ValueKind);
                defaultInterpolatedStringHandler.AppendLiteral("'.");
                throw new InvalidOperationException(defaultInterpolatedStringHandler.ToStringAndClear());
            }
            return string;
        }
        public static void WriteStringValue(this Utf8JsonWriter writer, DateTimeOffset value, string format)
        {
            writer.WriteStringValue(TypeFormatters.ToString(value, format));
        }
        public static void WriteStringValue(this Utf8JsonWriter writer, DateTime value, string format)
        {
            writer.WriteStringValue(TypeFormatters.ToString(value, format));
        }
        public static void WriteStringValue(this Utf8JsonWriter writer, TimeSpan value, string format)
        {
            writer.WriteStringValue(TypeFormatters.ToString(value, format));
        }
        public static void WriteStringValue(this Utf8JsonWriter writer, char value)
        {
            writer.WriteStringValue(value.ToString(CultureInfo.InvariantCulture));
        }
        public static void WriteBase64StringValue(this Utf8JsonWriter writer, byte[] value, string format)
        {
            if (value == null)
                writer.WriteNullValue();
            else if (!(format == "U")) {
                if (!(format == "D"))
                    throw new ArgumentException("Format is not supported: '" + format + "'", "format");
                writer.WriteBase64StringValue(value);
            } else {
                writer.WriteStringValue(TypeFormatters.ToBase64UrlString(value));
            }
        }
        public static void WriteNumberValue(this Utf8JsonWriter writer, DateTimeOffset value, string format)
        {
            if (format != "U")
                throw new ArgumentOutOfRangeException("format", "Only 'U' format is supported when writing a DateTimeOffset as a Number.");
            writer.WriteNumberValue(value.ToUnixTimeSeconds());
        }
        public static void WriteObjectValue<T>(this Utf8JsonWriter writer, T value)
        {
            if (value != null) {
                IUtf8JsonSerializable utf8JsonSerializable = value as IUtf8JsonSerializable;
                if (utf8JsonSerializable == null) {
                    byte[] array = value as byte[];
                    if (array == null) {
                        BinaryData val = value as BinaryData;
                        if (val == null) {
                            if (!(((object)value) is JsonElement)) {
                                if (((object)value) is int) {
                                    int value2 = value as int;
                                    writer.WriteNumberValue(value2);
                                } else if (((object)value) is decimal) {
                                    decimal value3 = value as decimal;
                                    writer.WriteNumberValue(value3);
                                } else if (((object)value) is double) {
                                    double num = value as double;
                                    if (double.IsNaN(num))
                                        writer.WriteStringValue("NaN");
                                    else
                                        writer.WriteNumberValue(num);
                                } else if (((object)value) is float) {
                                    float value4 = value as float;
                                    writer.WriteNumberValue(value4);
                                } else if (((object)value) is long) {
                                    long value5 = value as long;
                                    writer.WriteNumberValue(value5);
                                } else {
                                    string text = value as string;
                                    if (text == null) {
                                        if (((object)value) is bool) {
                                            bool value6 = value as bool;
                                            writer.WriteBooleanValue(value6);
                                        } else if (((object)value) is Guid) {
                                            Guid value7 = value as Guid;
                                            writer.WriteStringValue(value7);
                                        } else if (((object)value) is DateTimeOffset) {
                                            DateTimeOffset value8 = value as DateTimeOffset;
                                            writer.WriteStringValue(value8, "O");
                                        } else if (((object)value) is DateTime) {
                                            DateTime value9 = value as DateTime;
                                            writer.WriteStringValue(value9, "O");
                                        } else {
                                            IEnumerable<KeyValuePair<string, object>> enumerable = value as IEnumerable<KeyValuePair<string, object>>;
                                            if (enumerable == null) {
                                                IEnumerable<object> enumerable2 = value as IEnumerable<object>;
                                                if (enumerable2 == null) {
                                                    if (!(((object)value) is TimeSpan)) {
                                                        DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(19, 1);
                                                        defaultInterpolatedStringHandler.AppendLiteral("Not supported type ");
                                                        defaultInterpolatedStringHandler.AppendFormatted(value.GetType());
                                                        throw new NotSupportedException(defaultInterpolatedStringHandler.ToStringAndClear());
                                                    }
                                                    TimeSpan value10 = value as TimeSpan;
                                                    writer.WriteStringValue(value10, "P");
                                                } else {
                                                    writer.WriteStartArray();
                                                    foreach (object item in enumerable2) {
                                                        writer.WriteObjectValue<object>(item);
                                                    }
                                                    writer.WriteEndArray();
                                                }
                                            } else {
                                                writer.WriteStartObject();
                                                foreach (KeyValuePair<string, object> item2 in enumerable) {
                                                    writer.WritePropertyName(item2.Key);
                                                    writer.WriteObjectValue<object>(item2.Value);
                                                }
                                                writer.WriteEndObject();
                                            }
                                        }
                                    } else
                                        writer.WriteStringValue(text);
                                }
                            } else
                                (value as JsonElement).WriteTo(writer);
                        } else
                            writer.WriteBase64StringValue(BinaryData.op_Implicit(val));
                    } else
                        writer.WriteBase64StringValue(array);
                } else
                    utf8JsonSerializable.Write(writer);
            } else
                writer.WriteNullValue();
        }
        public static void WriteObjectValue(this Utf8JsonWriter writer, object value)
        {
            writer.WriteObjectValue<object>(value);
        }
    }
}