package {{ sdk.namespace | caseDot }}.models

import com.google.gson.annotations.SerializedName
import io.appwrite.extensions.jsonCast

/**
 * {{ definition.description }}
 */
{% if definition.properties | length != 0 or definition.additionalProperties %}data {% endif %}class {{ definition | modelType(spec) | raw }}(
    {%~ for property in definition.properties %}
    /**
     * {{ property.description }}
     */
    @SerializedName("{{ property.name | escapeKeyword | escapeDollarSign}}")
    {% if property.required -%} val
    {%- else -%} var
    {%- endif %} {{ property.name | escapeKeyword | removeDollarSign }}: {{ property | propertyType(spec) | raw }},

    {%~ endfor %}
    {%~ if definition.additionalProperties %}
    /**
     * Additional properties
     */
    @SerializedName("data")
    val data: T
    {%~ endif %}
) {
    fun toMap(): Map<String, Any> = mapOf(
        {%~ for property in definition.properties %}
        "{{ property.name | escapeDollarSign }}" to {% if property.sub_schema %}{% if property.type == 'array' %}{{property.name | escapeKeyword | removeDollarSign}}.map { it.toMap() }{% else %}{{property.name | escapeKeyword | removeDollarSign}}.toMap(){% endif %}{% else %}{{property.name | escapeKeyword | removeDollarSign}}{% endif %} as Any,
        {%~ endfor %}
        {%~ if definition.additionalProperties %}
        "data" to data!!.jsonCast(to = Map::class.java)
        {%~ endif %}
    )

    companion object {
        {%~ if definition.name | hasGenericType(spec) %}
        operator fun invoke(
            {%~ for property in definition.properties %}
            {{ property.name | escapeKeyword | removeDollarSign }}: {{ property | propertyType(spec, 'Map<String, Any>') | raw }},
            {%~ endfor %}
            {%~ if definition.additionalProperties %}
            data: Map<String, Any>
            {%~ endif %}
        ) = {{ definition | modelType(spec, 'Map<String, Any>') | raw }}(
            {%~ for property in definition.properties %}
            {{ property.name | escapeKeyword | removeDollarSign }},
            {%~ endfor %}
            {%~ if definition.additionalProperties %}
            data
            {%~ endif %}
        )
        {%~ endif %}

        @Suppress("UNCHECKED_CAST")
        fun {% if definition.name | hasGenericType(spec) %}<T> {% endif %}from(
            map: Map<String, Any>,
            {%~ if definition.name | hasGenericType(spec) %}
            nestedType: Class<T>
            {%~ endif %}
        ) = {{ definition | modelType(spec) | raw }}(
            {%~ for property in definition.properties %}
            {{ property.name | escapeKeyword | removeDollarSign }} = {% if property.sub_schema %}{% if property.type == 'array' %}(map["{{ property.name | escapeDollarSign }}"] as List<Map<String, Any>>).map { {{ property.sub_schema | caseUcfirst }}.from(map = it{% if property.sub_schema | hasGenericType(spec) %}, nestedType{% endif %}) }{% else %}{{ property.sub_schema | caseUcfirst }}.from(map = map["{{property.name | escapeDollarSign }}"] as Map<String, Any>{% if property.sub_schema | hasGenericType(spec) %}, nestedType{% endif %}){% endif %}{% else %}{% if property.type == "integer" or property.type == "number" %}({% endif %}map["{{ property.name | escapeDollarSign }}"]{% if property.type == "integer" or property.type == "number" %} as{% if not property.required %}?{% endif %} Number){% endif %}{% if property.type == "integer" %}{% if not property.required %}?{% endif %}.toLong(){% elseif property.type == "number" %}{% if not property.required %}?{% endif %}.toDouble(){% else %} as{% if not property.required %}?{% endif %} {{ property | propertyType(spec) | raw }}{% endif %}{% endif %},
            {%~ endfor %}
            {%~ if definition.additionalProperties %}
            data = map.jsonCast(to = nestedType)
            {%~ endif %}
        )
    }
}