{# -*- jinja2 -*- #}
#
# Pydantic model classes for MDF model '{{model.handle}}'
# Autogenerated by bento-mdf (MDFValidator)
#

import re
from typing import Optional, Annotated, List
from annotated_types import Predicate, Unit
from enum import Enum
from datetime import datetime
from pydantic import BaseModel, Field, WithJsonSchema, AnyUrl

def MatchedStrType(pat : str):
    return Annotated[str,
                     Predicate(re.compile(pat).fullmatch),
                     WithJsonSchema({"pattern":pat})]

# def URIType():
#     return MatchedStrType("^https?://.*")

def PathType():
    return MatchedStrType("^/.*")

{% for node in model.nodes.values() %}

{% for pr in node.props.values() %}
{% if pr.value_domain == 'value_set' or pr.item_domain == 'value_set' %}
{% if pr.value_set.url %}
class {{pr.handle | toCamelCase}}EnumURL(BaseModel):
    url: AnyUrl
{% elif pr.value_set.path %}
class {{pr.handle | toCamelCase}}EnumPath(BaseModel):
    path: PathType()
{% else %}
class {{pr.handle | toCamelCase}}Enum(str, Enum):
{% endif %}
{% for tm in pr.terms.values() %}
    {{tm.value | to_snakecase}} = '{{tm.value}}'
{% endfor %}
{% endif %}
{% endfor %}
  
class {{node.handle | toCamelCase }}(BaseModel):
{% for pr in node.props.values() %}
{% if pr.value_domain == 'value_set' or pr.item_domain == 'value_set'%}
{% if pr.value_set.url %}
    {{pr.handle}}: {{ [pr.handle | toCamelCase, 'EnumURL'] | join('') | maybe_list(pr) | maybe_optional(pr) }}
{% elif pr.value_set.path %}
    {{pr.handle}}: {{ [pr.handle | toCamelCase, 'EnumPath'] | join('') | maybe_list(pr) | maybe_optional(pr) }}
{% else %}
    {{pr.handle}}: {{ [pr.handle | toCamelCase, 'Enum'] | join('') | maybe_list(pr) | maybe_optional(pr) }}
{% endif %}
{% elif pr.value_domain == 'regexp' or pr.item_domain == 'regexp'%}
    {{pr.handle}}: {{ "MatchedStrType(r'{}')".format(pr.pattern) | maybe_list(pr) | maybe_optional(pr) }}
{% elif pr.value_domain == 'url' or pr.item_domain == 'url' %}
    {{pr.handle}}: {{ "AnyUrl" | maybe_list(pr) | maybe_optional(pr) }}
{% elif pr.value_domain == 'number' or pr.value_domain == 'integer' or
        pr.item_domain == 'number' or pr.item_domain == 'integer' %}
{% if pr.units %}
{% if pr.item_domain %}
    {{pr.handle}}: {{ pr.units | to_unit_types(typemap[pr.item_domain]) | join(' | ') | maybe_list(pr) | maybe_optional(pr) }}
{% else %}
    {{pr.handle}}: {{ pr.units | to_unit_types(typemap[pr.value_domain]) | join(' | ') | maybe_optional(pr) }}
{% endif %}
{% else %}
{% if pr.item_domain %}
    {{pr.handle}}: {{typemap[pr.item_domain].__name__ | maybe_list(pr) | maybe_optional(pr)}}
{% else %}
    {{pr.handle}}: {{typemap[pr.value_domain].__name__ | maybe_optional(pr)}}
{% endif %}
{% endif %}
{% elif pr.value_domain == 'datetime' or pr.item_domain == 'datetime' %}
    {{pr.handle}}: {{ "datetime" | maybe_list(pr) | maybe_optional(pr) }}
{% else %}
{% endif %}
{% endfor %}

{% endfor %}

class {{"{}Data".format(model.handle)}}(BaseModel):
{% for node in model.nodes.values() %}
    {{node.handle}}: {{node.handle | toCamelCase}}
{% endfor %}
  
