[System.CodeDom.Compiler.GeneratedCode("NSwag", "{{ ToolchainVersion }}")]
internal class JsonExceptionConverter : Newtonsoft.Json.JsonConverter
{
    private readonly Newtonsoft.Json.Serialization.DefaultContractResolver _defaultContractResolver = new Newtonsoft.Json.Serialization.DefaultContractResolver();
    private readonly System.Collections.Generic.IDictionary<string, System.Reflection.Assembly> _searchedNamespaces;
    private readonly bool _hideStackTrace = false;
    
    public JsonExceptionConverter()
    {
        _searchedNamespaces = new System.Collections.Generic.Dictionary<string, System.Reflection.Assembly> { { typeof({{ ExceptionModelClass }}).Namespace, System.Reflection.IntrospectionExtensions.GetTypeInfo(typeof({{ ExceptionModelClass }})).Assembly } };
    }
    
    public override bool CanWrite => true;
    
    public override void WriteJson(Newtonsoft.Json.JsonWriter writer, object value, Newtonsoft.Json.JsonSerializer serializer)
    {
        var exception = value as System.Exception;
        if (exception != null)
        {
            var resolver = serializer.ContractResolver as Newtonsoft.Json.Serialization.DefaultContractResolver ?? _defaultContractResolver;
    
            var jObject = new Newtonsoft.Json.Linq.JObject();
            jObject.Add(resolver.GetResolvedPropertyName("discriminator"), exception.GetType().Name);
            jObject.Add(resolver.GetResolvedPropertyName("Message"), exception.Message);
            jObject.Add(resolver.GetResolvedPropertyName("StackTrace"), _hideStackTrace ? "HIDDEN" : exception.StackTrace);
            jObject.Add(resolver.GetResolvedPropertyName("Source"), exception.Source);
            jObject.Add(resolver.GetResolvedPropertyName("InnerException"),
                exception.InnerException != null ? Newtonsoft.Json.Linq.JToken.FromObject(exception.InnerException, serializer) : null);
    
            foreach (var property in GetExceptionProperties(value.GetType()))
            {
                var propertyValue = property.Key.GetValue(exception);
                if (propertyValue != null)
                {
                    jObject.AddFirst(new Newtonsoft.Json.Linq.JProperty(resolver.GetResolvedPropertyName(property.Value),
                        Newtonsoft.Json.Linq.JToken.FromObject(propertyValue, serializer)));
                }
            }
    
            value = jObject;
        }
    
        serializer.Serialize(writer, value);
    }
    
    public override bool CanConvert(System.Type objectType)
    {
        return System.Reflection.IntrospectionExtensions.GetTypeInfo(typeof(System.Exception)).IsAssignableFrom(System.Reflection.IntrospectionExtensions.GetTypeInfo(objectType));
    }
    
    public override object ReadJson(Newtonsoft.Json.JsonReader reader, System.Type objectType, object existingValue, Newtonsoft.Json.JsonSerializer serializer)
    {
        var jObject = serializer.Deserialize<Newtonsoft.Json.Linq.JObject>(reader);
        if (jObject == null)
            return null;
    
        var newSerializer = new Newtonsoft.Json.JsonSerializer();
        newSerializer.ContractResolver = (Newtonsoft.Json.Serialization.IContractResolver)System.Activator.CreateInstance(serializer.ContractResolver.GetType());
    
        var field = GetField(typeof(Newtonsoft.Json.Serialization.DefaultContractResolver), "_sharedCache");
        if (field != null)
            field.SetValue(newSerializer.ContractResolver, false);
    
        dynamic resolver = newSerializer.ContractResolver;
        if (System.Reflection.RuntimeReflectionExtensions.GetRuntimeProperty(newSerializer.ContractResolver.GetType(), "IgnoreSerializableAttribute") != null)
            resolver.IgnoreSerializableAttribute = true;
        if (System.Reflection.RuntimeReflectionExtensions.GetRuntimeProperty(newSerializer.ContractResolver.GetType(), "IgnoreSerializableInterface") != null)
            resolver.IgnoreSerializableInterface = true;
    
        Newtonsoft.Json.Linq.JToken token;
        if (jObject.TryGetValue("discriminator", System.StringComparison.OrdinalIgnoreCase, out token))
        {
            var discriminator = Newtonsoft.Json.Linq.Extensions.Value<string>(token);
            if (objectType.Name.Equals(discriminator) == false)
            {
                var exceptionType = System.Type.GetType("System." + discriminator, false);
                if (exceptionType != null)
                    objectType = exceptionType;
                else
                {
                    foreach (var pair in _searchedNamespaces)
                    {
                        exceptionType = pair.Value.GetType(pair.Key + "." + discriminator);
                        if (exceptionType != null)
                        {
                            objectType = exceptionType;
                            break;
                        }
                    }
    
                }
            }
        }
    
        var value = jObject.ToObject(objectType, newSerializer);
        foreach (var property in GetExceptionProperties(value.GetType()))
        {
            var jValue = jObject.GetValue(resolver.GetResolvedPropertyName(property.Value));
            var propertyValue = (object)jValue?.ToObject(property.Key.PropertyType);
            if (property.Key.SetMethod != null)
                property.Key.SetValue(value, propertyValue);
            else
            {
                field = GetField(objectType, "m_" + property.Value.Substring(0, 1).ToLowerInvariant() + property.Value.Substring(1));
                if (field != null)
                    field.SetValue(value, propertyValue);
            }
        }
    
        SetExceptionFieldValue(jObject, "Message", value, "_message", resolver, newSerializer);
        SetExceptionFieldValue(jObject, "StackTrace", value, "_stackTraceString", resolver, newSerializer);
        SetExceptionFieldValue(jObject, "Source", value, "_source", resolver, newSerializer);
        SetExceptionFieldValue(jObject, "InnerException", value, "_innerException", resolver, serializer);
    
        return value;
    }
    
    private System.Reflection.FieldInfo GetField(System.Type type, string fieldName)
    {
        var field = System.Reflection.IntrospectionExtensions.GetTypeInfo(type).GetDeclaredField(fieldName);
        if (field == null && System.Reflection.IntrospectionExtensions.GetTypeInfo(type).BaseType != null)
            return GetField(System.Reflection.IntrospectionExtensions.GetTypeInfo(type).BaseType, fieldName);
        return field;
    }
    
    private System.Collections.Generic.IDictionary<System.Reflection.PropertyInfo, string> GetExceptionProperties(System.Type exceptionType)
    {
        var result = new System.Collections.Generic.Dictionary<System.Reflection.PropertyInfo, string>();
        foreach (var property in System.Reflection.RuntimeReflectionExtensions.GetRuntimeProperties(exceptionType))
        {
            if (property.GetMethod?.IsPublic != true)
            {
                continue;
            }

            var attribute = System.Reflection.CustomAttributeExtensions.GetCustomAttribute<Newtonsoft.Json.JsonPropertyAttribute>(property);
            var propertyName = attribute != null ? attribute.PropertyName : property.Name;

            switch (propertyName)
            {
                case "Message":
                case "StackTrace":
                case "Source":
                case "InnerException":
                case "Data":
                case "TargetSite":
                case "HelpLink":
                case "HResult":
                    break;
                default:
                    result[property] = propertyName;
                    break;
            }
        }
        return result;
    }
    
        private void SetExceptionFieldValue(Newtonsoft.Json.Linq.JObject jObject, string propertyName, object value, string fieldName, Newtonsoft.Json.Serialization.IContractResolver resolver, Newtonsoft.Json.JsonSerializer serializer)
        {
            var field = System.Reflection.IntrospectionExtensions.GetTypeInfo(typeof(System.Exception)).GetDeclaredField(fieldName);
            var jsonPropertyName = resolver is Newtonsoft.Json.Serialization.DefaultContractResolver ? ((Newtonsoft.Json.Serialization.DefaultContractResolver)resolver).GetResolvedPropertyName(propertyName) : propertyName;
            foreach (var property in jObject.Properties())
            {
                if (System.String.Equals(property.Name, jsonPropertyName, System.StringComparison.OrdinalIgnoreCase))
                {
                    var fieldValue = property.Value.ToObject(field.FieldType, serializer);
                    field.SetValue(value, fieldValue);
                    break;
                }
            }
        }
    }
