{% macro render_preamble(info) -%}
{%- if info -%}
# flake8:noqa
# isort:skip_file
##############################################################################
# Note: Generated by {{ info.module }} at {{ info.generated }}
#       Try to avoid editing it if you might need to regenerate it.
##############################################################################
{# [blank line] #}
{# [blank line] #}
{%- endif -%}
{%- endmacro %}

{% macro render_Schema(schema, location, known_types=None) -%}
Schema_{{ schema_name(schema) }} = xsd.Schema(
    imports=[{% for i in schema.imports %}Schema_{{ schema_name(i) }}{% if not loop.last %}, {% endif %}{% endfor %}],
    includes=[{% for i in schema.includes %}Schema_{{ schema_name(i) }}{% if not loop.last %}, {% endif %}{% endfor %}],
    targetNamespace='{{ schema.targetNamespace }}',
    {%- if location %}
    location='{{ location|url_template }}',{% endif %}
    elementFormDefault='{{ schema.elementFormDefault }}',
    simpleTypes=[{% for st in schema.simpleTypes %}{{ st.name|capitalize }}{% if not loop.last %}, {% endif %}{% endfor %}],
    attributeGroups=[{% for ag in schema.attributeGroups %}{{ ag.name|capitalize }}{% if not loop.last %}, {% endif %}{% endfor %}],
    groups=[{% for g in schema.groups %}{{ g.name|capitalize }}{% if not loop.last %}, {% endif %}{% endfor %}],
    complexTypes=[{% for ct in schema.complexTypes %}{{ ct.name|capitalize }}{% if not loop.last %}, {% endif %}{% endfor %}],
    elements={{ '{' }}{% for e in schema.elements %}'{{ e.name }}': xsd.Element({% if e.type %}{{ e|type(known_types) }}{% else %}{{ e.name|capitalize }}(){% endif %}{% if e.substitutionGroup %}, substitutionGroup="{{ e.substitutionGroup }}"{% endif %}){% if not loop.last %}, {% endif %}{% endfor %}{{ '}' }},
)
{%- if location %}
{# [blank line] #}
# XXX: Workaround for naming issues related to relative locations!
Schema_{{ schema_name(schema, location) }} = Schema_{{ schema_name(schema) }}
{%- endif %}
{# [blank line] #}
{# [blank line] #}
{%- endmacro %}

{% macro render_xsd_List(name, known_types=None) -%}
class {{ name|capitalize }}(xsd.List):
    pass
{# [blank line] #}
{# [blank line] #}
{%- endmacro %}

{% macro render_xsd_AttributeGroup(attrGroup, known_types=None) -%}
class {{ attrGroup.name|capitalize }}(xsd.AttributeGroup):
    {%- for attribute in attrGroup.attributes %}
    {%- set name = attribute.ref|remove_namespace if attribute.ref else attribute.name %}
    {{ name|fix_keyword }} = xsd.Attribute({{ attribute|type(known_types) }}{% if name in keywords %}, tagname='{{ name }}'{% endif %}, use={{ attribute.use|default('optional', true)|use }})
    {%- endfor %}
{# [blank line] #}
{# [blank line] #}
{%- endmacro %}

{% macro render_xsd_Group(group, known_types=None) -%}
class {{ group.name|capitalize }}(xsd.Group):
    {%- for element in group.sequence.elements %}
    {%- set name = element.ref|remove_namespace if element.ref else element.name %}
    {{ name|fix_keyword }} = xsd.Element({{ element|type(known_types) }}{% if name in keywords %}, tagname='{{ name }}'{% endif %})
    {%- endfor %}
{# [blank line] #}
{# [blank line] #}
{%- endmacro %}

{% macro render_xsd_Restriction(name, restriction, known_types=None) -%}
class {{ name|capitalize }}({{ restriction|type(known_types) }}):
{%- if restriction.enumerations %}
    enumeration = [{% for enum in restriction.enumerations %}'{{ enum.value }}'{% if not loop.last %}, {% endif %}{% endfor %}]
{%- endif %}
{%- if restriction.pattern %}
    pattern = r'{{ restriction.pattern.value }}'
{%- endif %}
{%- if restriction.minInclusive %}
    minInclusive = r'{{ restriction.minInclusive.value }}'
{%- elif restriction.minExclusive %}
    minExclusive = r'{{ restriction.minExclusive.value }}'
{%- endif %}
{%- if restriction.maxInclusive %}
    maxInclusive = r'{{ restriction.maxInclusive.value }}'
{%- elif restriction.maxExclusive %}
    maxExclusive = r'{{ restriction.maxExclusive.value }}'
{%- endif %}
{%- if not restriction.enumerations and not restriction.pattern
        and not restriction.minInclusive and not restriction.minExclusive
        and not restriction.maxInclusive and not restriction.maxExclusive %}
    pass
{%- endif %}
{# [blank line] #}
{# [blank line] #}
{%- endmacro %}

{% macro render_complexType(class_name, content, known_types=None) -%}
{%- set ct = content %}
{%- if not ct.sequence and not ct.complexContent %}
class {{ class_name|capitalize }}(xsd.ComplexType):
    pass
{%- endif %}
{%- if ct.complexContent %}
    {%- if ct.complexContent.restriction %}
class {{ ct.name|capitalize }}({{ ct.complexContent.restriction|type(known_types) }}):
    INHERITANCE = xsd.Inheritance.RESTRICTION
    {%- set content = ct.complexContent.restriction %}
    {%- else %}
class {{ ct.name|capitalize }}({{ ct.complexContent.extension|type(known_types) }}):
    INHERITANCE = xsd.Inheritance.EXTENSION
    {%- set content = ct.complexContent.extension %}
    {%- endif %}
{%- elif ct.sequence %}
class {{ class_name|capitalize }}(xsd.ComplexType):
    INHERITANCE = None
    {%- set content = ct %}
{%- endif %}
{%- if content.sequence %}
    INDICATOR = xsd.Sequence
    {%- set elements = content.sequence.elements %}
{%- elif content.all %}
    INDICATOR = xsd.All
    {%- set elements = content.all.elements %}
{%- elif content.choice %}
    INDICATOR = xsd.Choice
    {%- set elements = content.choice.elements %}
{%- endif %}
{%- for attribute in content.attributes %}
    {%- set name = attribute.ref|remove_namespace if attribute.ref else attribute.name %}
    {{ name|fix_keyword }} = xsd.Attribute({{ attribute|type(known_types) }}{% if name in keywords %}, tagname='{{ name }}'{% endif %}, use={{ attribute.use|default('optional', true)|use }})
{%- endfor %}
{%- for attrGroupRef in content.attributeGroups %}
    {{ attrGroupRef.ref|remove_namespace }} = xsd.Ref({{ attrGroupRef.ref|type(known_types) }})
{%- endfor %}
{%- for element in elements -%}
    {{ render_xsd_element(element, known_types) }}
{%- endfor %}
{%- if content.sequence %}
{{ render_create_method(elements, known_types) }}
{%- endif %}
{# blank line #}
{# blank line #}
{%- endmacro %}

{% macro render_xsd_element(element, known_types=None) -%}
    {%- set field_type = 'ListElement' if element.maxOccurs and element.maxOccurs > 1 else 'Element' %}
    {%- if element.type %}
    {{ element.name|fix_keyword }} = xsd.{{ field_type }}({{ element|type(known_types) }}{% if element.name in keywords or element.maxOccurs and element.maxOccurs > 1 %}, tagname='{{ element.name }}'{% endif %}{% if element.minOccurs is not none %}, minOccurs={{ element.minOccurs|upper }}{% endif %}{% if element.maxOccurs and element.maxOccurs > 1 %}, maxOccurs={{ element.maxOccurs|max_occurs }}{% endif %}{% if element.nillable %}, nillable=True{% endif %})
    {%- endif %}
    {%- if element.simpleType %}
    {{ element.name|fix_keyword }} = xsd.Element({{ element.simpleType.restriction|type(known_types) }}(
    {%- if element.simpleType.restriction.enumerations -%}
    enumeration=[{% for enum in element.simpleType.restriction.enumerations %}'{{ enum.value }}'{% if not loop.last %}, {% endif %}{% endfor %}],
    {%- endif %}
    {%- if element.name in keywords %}tagname='{{ element.name }}',{% endif %}
    {%- if element.simpleType.restriction.minInclusive %}minInclusive={{ element.simpleType.restriction.minInclusive.value }},{% endif %}
    {%- if element.simpleType.restriction.maxInclusive %}maxInclusive={{ element.simpleType.restriction.maxInclusive.value }},{% endif %}
    {%- if element.simpleType.restriction.minExclusive %}minExclusive={{ element.simpleType.restriction.minExclusive.value }},{% endif %}
    {%- if element.simpleType.restriction.maxExclusive %}maxExclusive={{ element.simpleType.restriction.maxExclusive.value }},{% endif %}
    {%- if element.simpleType.restriction.fractionDigits %}fractionDigits={{ element.simpleType.restriction.fractionDigits.value }},{% endif %}
    {%- if element.simpleType.restriction.totalDigits %}totalDigits={{ element.simpleType.restriction.totalDigits.value }},{% endif %}
    {%- if element.simpleType.restriction.pattern %}pattern=r'{{ element.simpleType.restriction.pattern.value }}',{% endif %}
    {%- if element.simpleType.restriction.length %}length={{ element.simpleType.restriction.length.value }},{% endif %}
    {%- if element.simpleType.restriction.minLength %}minLength={{ element.simpleType.restriction.minLength.value }},{% endif %}
    {%- if element.simpleType.restriction.maxLength %}maxLength={{ element.simpleType.restriction.maxLength.value }},{% endif %}
    {%- if element.simpleType.restriction.whiteSpace %}whiteSpace={{ element.simpleType.restriction.whiteSpace.value }},{% endif %}))
    {%- endif %}
    {%- if element.ref %}
    {{ element.ref|remove_namespace }} = xsd.Ref({{ element|type(known_types) }})
    {%- endif %}
{%- endmacro %}

{% macro render_create_method(elements, known_types=None) -%}
{# [blank line] #}
    @classmethod
    def create(cls{% for e in elements %}{% if e.minOccurs == 1 or e.minOccurs is none %}, {{ e.ref|remove_namespace|fix_keyword if e.ref else e.name|fix_keyword }}{% endif %}{% endfor %}):
        instance = cls()
        {%- for element in elements %}
        {%- if element.minOccurs is not none and element.minOccurs != 1 %}{% continue %}{% endif %}
        {%- set name = element.ref|remove_namespace if element.ref else element.name %}
        instance.{{ name|fix_keyword }} = {{ name|fix_keyword }}
        {%- endfor %}
        return instance
{%- endmacro %}
{#- vim:set et ft=django nowrap sts=4 sw=4 ts=4: -#}
