// this file was generated by a tool 
{%- set schema_name = class_name | pascal -%}
{%- set list_type = "Array" %}
{%- set schema = root %}

{%- macro getTypeScriptType(propertyName, property) %}
    {%- set typeScriptType = "" -%}
    {%- if property.type == 'integer' or property.type == 'number' -%}
        {%- set typeScriptType = "number" -%}
    {%- elif property.type == 'string' -%}
        {%- if property.format == 'date-time' -%}
            {%- set typeScriptType = "Date" -%}
        {%- elif property.format == 'date' -%}
            {%- set typeScriptType = "Date" -%}
        {%- elif property.format == 'time' -%}
            {%- set typeScriptType = "Date" -%}
        {%- else -%}
            {%- set typeScriptType = "string" -%}
        {%- endif -%}
    {%- elif property.type == 'array' -%}
        {%- if property.items.type == 'integer' or property.items.type == 'number' -%}
            {%- set typeScriptType = list_type+"<number>" -%}
        {%- elif property.items.type == 'string' -%}
            {%- if property.items.format == 'date-time' or property.items.format == 'date' or property.items.format == 'time' -%}
                {%- set typeScriptType = list_type+"<Date>" -%}
            {%- else -%}
                {%- set typeScriptType = list_type+"<string>" -%}
            {%- endif -%}
        {%- elif property.items['$ref'] -%} 
            {%- set ref = property.items['$ref'] -%}
            {%- set typeScriptType = list_type+"<"+(ref | schema_type( project_name, root) | pascal)+">" -%}
        {%- elif 'type' in property['items'] and property['items']['type'] == "object" and 'properties' in property['items'] -%}
            {% set itemTypeScriptType = schema_name + ((propertyName + "Item") | pascal) %}
            {%- set typeScriptType = list_type+"<"+itemTypeScriptType+">" -%}
            {%- if not itemTypeScriptType in stack("classes") -%}
            {{ emitclass( property['items'], itemTypeScriptType) | push(schema_name) }}
            {%- endif -%}
        {%- else -%}
            {%- set typeScriptType = list_type+"<object>" -%}
        {%- endif -%}
    {%- else -%}
        {%- set typeScriptType = "object" -%}
    {%- endif -%}
    {%- if (not property.type) or property.type == "object"  -%}
        {%- if property['$ref'] -%}
            {%- set ref = property['$ref'] -%}
            {%- set typeScriptType = ref | schema_type( project_name, root) | pascal -%}
        {%- elif property.properties -%}
            {%- set typeScriptType = schema_name + ( propertyName | pascal ) -%}
            {%- if not typeScriptType in stack("classes") -%}
            {{ emitclass( property, typeScriptType ) | push(schema_name) }}
            {%- endif -%}
        {%- endif -%}
    {%- endif -%}
    {{ typeScriptType }}
{%- endmacro -%}

{%- macro emitclass(type, type_name) -%}
{%- if type.type == 'object' or not type.type -%}
{{- type_name | pascal | push("classes") }}
{{- type_name | pascal | push(schema_name+"_classes") }}
export class {{ type_name | pascal }}
{%- if type.allOf -%}
    {%- for allOfType in type.allOf -%}
        {%- if loop.first -%}
        {%- if allOfType['$ref'] -%}
 extends {{ allOfType['$ref'] | schema_type( project_name, root) | pascal }}
        {%- endif -%}
        {%- endif -%}
    {%- endfor -%}
{%- endif %}
{
    static fromData(data?: Record<string, unknown>): {{ type_name | pascal }}
    {
        return new {{ type_name | pascal }}( data );
    }

    public toByteArray(): Uint8Array 
    {
        const jsonString = JSON.stringify(this);
        const utf8Encoded = new TextEncoder().encode(jsonString);
        return utf8Encoded;
    }
{% if type.properties %}
     constructor(data?: Record<string, unknown>) {
{% for pn, property in type.properties.items()  -%}
    {%- set propertyName = pn | strip_invalid_identifier_characters %}
    {%- set typeScriptType = getTypeScriptType(propertyName, property )%}
        if (data?.{{ propertyName | camel }} !== undefined) {
            this._{{ propertyName | camel }} = data.{{ propertyName | camel }} as {{ typeScriptType }};
        } else {
            this._{{ propertyName | camel }} = {} as {{ typeScriptType }};
        }
{%- endfor %}
     }
{% for pn, property in type.properties.items()  -%}
    {%- set propertyName = pn | strip_invalid_identifier_characters %}
    {%- set typeScriptType = getTypeScriptType(propertyName, property )%}
    {%- if property.enum %}
    _{{ propertyName | camel }}: string = "{{ property.enum[0] }}";
    {%- if property.description %} 
    /** {{property.description}} */
    {%- endif %}
    get {{ propertyName | camel }}(): string
    {
        return this._{{ propertyName | camel }};
    }
    set {{ propertyName | camel }}(value: string)
    {
        const validValues = [{% for value in property.enum %}"{{ value }}"{% if not loop.last %}, {% endif %}{% endfor %}];
        if (!validValues.includes(value))
        {
            throw new RangeError(`Invalid value for {{ propertyName | pascal }}: ${value}. Valid values are: ${validValues.join(", ")}`);
        }
        this._{{ propertyName | camel }} = value;
    }
    {%- else %}
    _{{ propertyName | camel }}: {{ typeScriptType }};
    {%- if property.description %} 
    /** {{property.description}} */
    {%- endif %}
    get {{ propertyName | camel }}(): {{ typeScriptType }}
    {
        return this._{{ propertyName | camel }};
    }
    set {{ propertyName | camel }}(value: {{ typeScriptType }})
    {
        {%- if property.minimum is defined %}
        if (typeof value === 'number' && value < {{ property.minimum }})
        {
            throw new RangeError(`Value for {{ propertyName | pascal }} (${value}) is too small. Minimum is {{ property.minimum }}.`);
        }
        {%- endif -%}
        {%- if property.exclusiveMinimum is defined %}
        if (typeof value === 'number' && value <= {{ property.exclusiveMinimum }})
        {
            throw new RangeError(`Value for {{ propertyName | pascal }} (${value}) must be greater than {{ property.exclusiveMinimum }}.`);
        }
        {%- endif -%}
        {%- if property.maximum is defined %}
        if (typeof value === 'number' && value > {{ property.maximum }})
        {
            throw new RangeError(`Value for {{ propertyName | pascal }} (${value}) is too large. Maximum is {{ property.maximum }}.`);
        }
        {%- endif -%}
        {%- if property.exclusiveMaximum is defined %}
        if (typeof value === 'number' && value >= {{ property.exclusiveMaximum }})
        {
            throw new RangeError(`Value for {{ propertyName | pascal }} (${value}) must be less than {{ property.exclusiveMaximum }}.`);
        }
        {%- endif -%}
        {%- if property.maxLength is defined %}
        if (typeof value === 'string' && value.length > {{ property.maxLength }})
        {
            throw new RangeError(`Value for {{ propertyName | pascal }} is too long (${value.length} characters). Maximum length is {{ property.maxLength }}.`);
        }
        {%- endif -%}
        {%- if property.minLength is defined %}
        if (typeof value === 'string' && value.length < {{ property.minLength }})
        {
            throw new RangeError(`Value for {{ propertyName | pascal }} is too short (${value.length} characters). Minimum length is {{ property.minLength }}.`);
        }
        {%- endif -%}
        {%- if property.pattern %}
        if (typeof value === 'string' && !/{{ property.pattern }}/.test(value))
        {
            throw new RangeError(`Value for {{ propertyName | pascal }} does not match required pattern: {{ property.pattern }}`);
        }
        {%- endif -%}
        {%- if property.format == "email" %}
        const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
        if (typeof value === 'string' && !emailRegex.test(value))
        {
            throw new TypeError(`Value for {{ propertyName | pascal }} is not a valid email address.`);
        }
        {%- endif %}
        this._{{ propertyName | camel }} = value;
    }
    {% endif -%}
{%- endfor -%}
{%- endif %}
}
{% endif -%}
{%- endmacro %}



{{- emitclass(schema, schema_name) }}

{% for item in stack(schema_name) %}
  {{ item }}
{%- endfor %}
