"""
DO NOT MODIFY THIS FILE.  It is automatically generated and changes will be over-written
on the next generation.

It contains enumerations used by the {{stinger.name}} interface.

LICENSE: This generated code is not subject to any license restrictions from the generator itself.
TODO: Get license text from stinger file
"""
{%macro field_list(arg_list)%}
model_config = ConfigDict(populate_by_name=True)
{%for arg in arg_list-%}
{%set field_desc %}Field({%if arg.description%}description="{{arg.description}}", {%endif%}{%if (arg.name|snake_case) != arg.name %}alias="{{arg.name}}"{%endif%}){%endset%}
{%-if arg.arg_type.name.lower() == 'primitive' -%}
{{arg.name|snake_case}}: Annotated[{%if arg.optional%}Optional[{{arg.python_local_type}}]{%else%}{{arg.python_local_type}}{%endif%}, {{field_desc}}]
{%elif arg.arg_type.name.lower() == 'enum'-%}
{{arg.name|snake_case}}: Annotated[{%if arg.optional%}Optional[{{arg.python_local_type}}]{%else%}{{arg.python_local_type}}{%endif%}, {{field_desc}}]
{%elif arg.arg_type.name.lower() == 'struct'-%}
{{arg.name|snake_case}}: Annotated[{%if arg.optional%}Optional[{{arg.python_local_type}}]{%else%}{{arg.python_local_type}}{%endif%}, {{field_desc}}]
{%elif arg.arg_type.name.lower() == 'datetime'-%}
{{arg.name|snake_case}}: Annotated[{%if arg.optional%}Optional[datetime]{%else%}datetime{%endif%}, {{field_desc}}]
{%elif arg.arg_type.name.lower() == 'duration'-%}
{{arg.name|snake_case}}: Annotated[{%if arg.optional%}Optional[timedelta]{%else%}timedelta{%endif%}, {{field_desc}}]
{%elif arg.arg_type.name.lower() == 'binary'-%}
{{arg.name|snake_case}}: Annotated[{%if arg.optional%}Optional[bytes]{%else%}bytes{%endif%}, {{field_desc}}, PlainValidator(base64_decode_if_str), PlainSerializer(lambda v: base64.b64encode(v).decode('utf-8'){%if arg.optional%} if v is not None else None{%endif%})]
{%elif arg.arg_type.name.lower() == 'array'-%}
{%if arg.element.arg_type.name.lower() == 'binary'-%}
{{arg.name|snake_case}}: Annotated[{%if arg.optional%}Optional[List[bytes]]{%else%}List[bytes]{%endif%}, {{field_desc}}, PlainValidator(lambda arr: [base64_decode_if_str(v) for v in arr]), PlainSerializer(lambda arr: [base64.b64encode(v).decode("utf-8") for v in arr])]

{%else%}
{{arg.name|snake_case}}: Annotated[{%if arg.optional%}Optional[List[{{arg.element.python_local_type}}]]{%else%}List[{{arg.element.python_local_type}}]{%endif%}, {{field_desc}}]
{%endif%}{# end array element cases #}

{%endif-%}
{%endfor%}
{%endmacro%}


from pydantic import BaseModel, Field, PlainValidator, PlainSerializer, ConfigDict
from datetime import datetime, timedelta, UTC
from typing import Optional, Annotated, Union, List
import base64
{%if stinger.uses_enums()%}from enum import IntEnum{%endif%}

def base64_decode_if_str(value: Union[str, bytes, None]) -> Optional[bytes]:
    """ If the value is a string, decode it from base64 to bytes.  Otherwise return the bytes as-is."""
    if isinstance(value, str):
        return base64.b64decode(value)
    return value

class InterfaceInfo(BaseModel):
    interface_name: str = Field(default="{{stinger.name}}")
    title: str = Field(default="{{stinger.title or stinger.name}}")
    version: str = Field(default="{{stinger.version}}")
    instance: str
    connection_topic: str
    timestamp: str

{%for ie_name, ie in stinger.enums.items() %}
class {{ie_name | UpperCamelCase }}(IntEnum):
    """ Interface enum `{{ie_name}}`."""
    {%-for value in ie.values %}
    {{value | CONST_CASE}} = {{loop.index}}
    {%-endfor%}
{%endfor%}

{%-for istruct_name, istruct in stinger.structs.items() %}
class {{istruct_name | UpperCamelCase }}(BaseModel):
    """ Interface struct `{{istruct_name}}`. """
    {{field_list(istruct.members)|indent(4)}}
{%endfor%}

{%-for signal_name, signal in stinger.signals.items()%}
class {{signal_name|UpperCamelCase}}SignalPayload(BaseModel):
    """ Interface signal `{{signal_name}}`. {%if signal.documentation%}
    
    {{signal.documentation}}{%endif%}
    """
    {{field_list(signal.arg_list)|indent(4)}}
{%endfor%}

{%-for prop_name, prop in stinger.properties.items()%}
class {{prop_name|UpperCamelCase}}Property(BaseModel):
    """ Interface property `{{prop_name}}` (multi-value struct).{%if prop.documentation%}
    
    {{prop.documentation}}{%endif%}
    """
    {{field_list(prop.arg_list)|indent(4)}}
{%endfor%}

{%- for method_name, method in stinger.methods.items()%}
class {{method_name|UpperCamelCase}}MethodRequest(BaseModel):
    """ Interface method `{{method_name}}` request object. {%if method.documentation%}

    {{method.documentation}}{%endif%}
    """
    {{field_list(method.arg_list)|indent(4)}}


class {{method_name|UpperCamelCase}}MethodResponse(BaseModel):
    """ Interface method `{{method_name}}` response object. {%if method.documentation%}

    {{method.documentation}}{%endif%}
    """
    {{field_list(method.return_arg_list)|indent(4)}}
{%endfor%}