{%- macro restriction(inner_text, css_class_name) -%}
    <p><span class="badge badge-light restriction {{ css_class_name }}-restriction">{{ inner_text }}</span></p>
{%- endmacro -%}

{%- macro tabbed_section(operator, property, property_path, index) -%}
    <h2 class="handle">
      <label>{% if operator == "allOf" -%}All of{% elif operator == "anyOf" -%}Any of{% elif operator == "oneOf" -%}One of{% endif -%}</label>
    </h2>
    {%- set tab_label = "Option" -%}
    {%- if operator == "allOf" -%}
        {%- set tab_label = "Requirement" -%}
    {%- endif -%}
    <ul class="nav nav-tabs" id="tabs{{ index }}_{{ operator }}" role="tablist">
        {%- for _ in property[operator] -%}
            {%- set tab_id = index ~ "__option" ~ loop.index -%}
            <li class="nav-item">
                <a class="nav-link {% if loop.index == 1 -%}active {% endif -%} {{ operator }}-option"
                   id="{{ tab_id }}" data-toggle="tab" href="#tab-pane_{{ tab_id }}" role="tab"
                   onclick="setAnchor('#{{ tab_id }}')"
                >{{ tab_label }} {{ loop.index }}</a>
            </li>
        {%- endfor -%}
    </ul>
    <div class="tab-content card">
        {%- for element in property[operator] -%}
            {%- set tab_id = index ~ "__option" ~ loop.index -%}
            <div class="tab-pane fade card-body {% if loop.index == 1 -%}active show{% endif -%}"
                 id="tab-pane_{{ tab_id }}" role="tabpanel">
                {{ content(tab_id, tab_label ~ " " ~ loop.index, element, property_path, True) }}
            </div>
        {%- endfor -%}
    </div>
{%- endmacro -%}

{%- macro add_description(property) -%}
    {%- set description = property.get("description") | get_description -%}
    {# Display description #}
    {%- if description -%}
        {%- if description is description_short -%}
            <span class="description">{{ description | markdown }}</span>
        {%- else -%}
            <div class="description collapse" id="collapseDescription{{ index }}">
                {{ description | markdown }}
            </div>
            <a class="collapse-description-link collapsed" data-toggle="collapse" href="#collapseDescription{{ index }}" aria-expanded="false" aria-controls="collapseDescription{{ index }}"></a>
        {%- endif -%}
    {%- endif -%}
{%- endmacro -%}

{%- macro content(index, property_name, property, property_path, named_property) -%}
    {%- set property, property_path = (property | resolve_ref(schema, property_path)) -%}

    {# Handle having oneOf or allOf with only one condition #}
    {%- if "allOf" in property and (property["allOf"] | length) == 1 -%}
        {{ add_description(property) }}
        {{ content(index, property_name, property["allOf"][0], property_path, True) }}
    {%- elif "anyOf" in property and (property["anyOf"] | length) == 1 -%}
        {{ add_description(property) }}
        {{ content(index, property_name, property["anyOf"][0], property_path, True) }}
    {%- else -%}
        {# Resolve type #}
        {%- set default, has_default = property | get_default -%}
        {%- set type = property | get_type_name -%}

        {# Display type #}
        {%- if not property is combining -%}
            <span class="badge badge-dark value-type">Type: {{ type }}</span>
        {%- endif -%}
        {%- if has_default -%}
            {{ " " }}<span class="badge badge-success default-value">Default: {{ default | python_to_json }}</span>
        {%- endif -%}

        {{ add_description(property) }}
    
        {# Handle actual requirement #}
        {%- if "allOf" in property -%}
            <div class="all-of-value">{{ tabbed_section("allOf", property, property_path, index) }}</div>
        {%- endif -%}
        {%- if "anyOf" in property -%}
            <div class="any-of-value">{{ tabbed_section("anyOf", property, property_path, index) }}</div>
        {%- endif -%}
        {%- if "oneOf" in property -%}
            <div class="one-of-value">{{ tabbed_section("oneOf", property, property_path, index) }}</div>
        {%- endif -%}
        {%- if "not" in property -%}
            <div class="not-value">
            <h4>Must <strong>not</strong> be:</h4>
            <div class="card">
                <div class="card-body">
                {{ content(index ~ "_not", property_name, property["not"], property_path, True) }}
                </div>
            </div>
            </div>
        {%- endif -%}
        {%- if "enum" in property -%}
            <div class="enum-value">
            <h4>Must be one of:</h4>
            <ul class="list-group">
            {%- for enum_choice in property.enum -%}
                <li class="list-group-item">{{ enum_choice | python_to_json }}</li>
            {%- endfor -%}
            </ul>
            </div>
        {%- endif -%}
        {%- if "const" in property -%}
            <span class="const-value">Specific value: <code>{{ property.const | python_to_json }}</code></span>
        {%- endif -%}
        {%- if "pattern" in property -%}
            <span class="pattern-value">Must match regular expression: <code>{{ property.pattern }}</code></span>
        {%- endif -%}
        {%- if not named_property -%}
            <span class="pattern-value">Property name must match regular expression: <code>{{ property_name }}</code></span>
        {%- endif -%}
        {%- if type == "string" -%}
            {%- if "minLength" in property -%}
                {{ restriction("Must be at least <code>" ~ property.minLength ~ "</code> characters long", "min-length") }}
            {%- endif -%}
            {%- if "maxLength" in property -%}
                {{ restriction("Must be at most <code>" ~ property.maxLength ~ "</code> characters long", "max-length") }}
            {%- endif -%}
        {%- endif -%}
        {%- if type in ["integer", "number"] -%}
            {%- set restriction_text = (property | get_numeric_restrictions_text("<code>", "</code>")) -%}
            {%- if restriction_text -%}
                {{ restriction(property | get_numeric_restrictions_text("<code>", "</code>"), "numeric") }}
            {%- endif -%}
        {%- endif -%}
        {%- if type.startswith("array") -%}
            {%- if "minItems" in property -%}
                {{ restriction("Must contain a minimum of <code>" ~ property.minItems ~ "</code> items", "min-items") }}
            {%- endif -%}
            {%- if "maxItems" in property -%}
                {{ restriction("Must contain a maximum of <code>" ~ property.maxItems ~ "</code> items", "max-items") }}
            {%- endif -%}
            {%- if "uniqueItems" in property and property.uniqueItems == True -%}
                {{ restriction("All items must be unique", "unique-items") }}
            {%- endif -%}
            {%- if "items" in property and property["items"] is mapping and property["items"] != {} -%}
                <h4>Each item of this array must be:</h4>
                <div class="card">
                    <div class="card-body items-definition">
                        {# Note that property["items"] is needed here because property.items is a function #}
                        {{ content(index ~ "_items", property_name ~ " Items", property["items"], property_path, True) }}
                    </div>
                </div>
            {%- endif -%}
            {%- if "contains" in property and property["contains"] != {} -%}
                <h4>At least one of the items must be:</h4>
                <div class="card">
                    <div class="card-body items-contain-definition">
                    {{ content(index ~ "_not", property_name, property["contains"], property_path, True) }}
                    </div>
                </div>
            {%- endif -%}
        {%- endif -%}

        {%- set examples = (property.get("examples") or []) -%}
		{# Display examples #}
		{%- if examples -%}
            <br/>
            <div class="badge badge-secondary">Example{% if examples|length > 1 %}s{% endif %}:</div>
            <br/>

            {%- set sanitized_index = index | escape_property_name_for_id -%}
            {%- for example in examples -%}
                {%- set example_id = sanitized_index ~ "_ex" ~ loop.index -%}
                {%- set example_is_long = example is not description_short -%}
                {%- if example_is_long -%}
                    <button class="btn btn-light example-show collapsed" data-toggle="collapse" data-target="#{{ example_id }}" aria-controls="{{ example_id }}"></button>
                {%- endif -%}
                <div id="{{ example_id }}" class="{% if example_is_long %}collapse {% endif %}jumbotron examples">
                    <pre>{{ example | to_pretty_json }}</pre>
                </div>
            {%- endfor -%}
		{%- endif -%}

        {%- if "properties" in property -%}
            {%- set required_properties = property.get("required") or [] -%}
            {%- for sub_property_name, sub_property in property["properties"].items() -%}
                {{ subsection(False, loop.index, index, sub_property_name, sub_property, required_properties, property_path, True) }}
            {%- endfor -%}
        {%- endif -%}
        {%- if "patternProperties" in property -%}
            {%- for sub_property_name, sub_property in property["patternProperties"].items() -%}
                {{ subsection(False, loop.index, index, sub_property_name, sub_property, [], property_path, False) }}
            {%- endfor -%}
        {%- endif -%}
    {%- endif -%}
{%- endmacro -%}

{%- macro subsection(expanded, index, parent, property_name, property, required_properties, property_path, named_property) -%}
    {# Resolve reference #}
    {%- set property, property_path = (property | resolve_ref(schema, property_path)) -%}

    {%- set suffix = property_name -%}
    {%- if parent != "" -%}
        {%- set suffix = parent ~ "__" ~ suffix -%}
    {%- endif -%}
    {%- if named_property -%}
        {%- set suffix = suffix | escape_property_name_for_id -%}
    {%- else -%}
        {%- set suffix = parent | generate_id_for_pattern_property(index) -%}
        {%- if "title" in property -%}
            {%- set property_title = property['title'] -%}
        {%- else -%}
            {%- set property_title = property_name -%}
        {%- endif -%}
    {%- endif -%}

    {%- set is_required = property_name in required_properties -%}
    <div class="accordion" id="accordion{{ suffix }}">
        <div class="card">
            <div class="card-header" id="heading{{ suffix }}">
                <h2 class="mb-0">
                    <button class="btn btn-link property-name-button" type="button" data-toggle="collapse" data-target="#{{ suffix }}"
                            aria-expanded="{{ expanded }}" aria-controls="{{ suffix }}" onclick="setAnchor('#{{ suffix }}')">
                        {%- if named_property -%}
                            <span class="property-name">{{ property_name }}</span>
                        {%- else -%}
                            <span class="property-name">{{ property_title }}</span>
                        {%- endif -%}
                        {%- if is_required -%}
                            {{ " " }}<span class="badge badge-warning required-property">Required</span>
                        {%- endif -%}
                        {%- if property is deprecated -%}
                            {{ " " }}<span class="badge badge-danger deprecated-property">Deprecated</span>
                        {%- endif -%}
                        {%- if not named_property -%}
                            {{ " " }}<span class="badge badge-info pattern-property">Pattern Property</span>
                        {%- endif -%}
                    </button>
                </h2>
            </div>

            <div id="{{ suffix }}"
                 class="collapse{% if expanded %} show{% endif %} property-definition-div" aria-labelledby="heading{{ suffix }}"
                 data-parent="#accordion{{ suffix }}">
              <div class="card-body">
                {{ content(suffix, property_name, property, property_path, named_property) }}
              </div>
            </div>
        </div>
    </div>
{%- endmacro -%}

<!DOCTYPE html>
<html lang="en">
<head>
    <link rel="stylesheet" type="text/css" href="https://fonts.googleapis.com/css?family=Overpass:300,400,600,800">
    <script src="https://code.jquery.com/jquery-3.4.1.min.js" integrity="sha256-CSXorXvZcTkaix6Yvo6HppcZGetbYMGWSFlBw8HfCJo=" crossorigin="anonymous"></script>
    <link href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">
    <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js" integrity="sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM" crossorigin="anonymous"></script>
	<link rel="stylesheet" type="text/css" href="schema_doc.css">
    <script src="https://use.fontawesome.com/facf9fa52c.js"></script>
    <script src="schema_doc.min.js"></script>
    <meta charset="utf-8"/>
    {%- set title = schema.get("title") -%}
    <title>{%- if title -%}{{ title }}{%- else -%}Schema Docs{%- endif -%}</title>
</head>
<body onload="anchorOnLoad();">
    {%- if title -%}
        <h1>{{ title }}</h1>
    {%- endif -%}
    {%- set properties = schema.get("properties") -%}
    {%- set patternProperties = schema.get("patternProperties") -%}
    {%- if expand_buttons -%}
        <div class="text-right">
            <button class="btn btn-primary" type="button" data-toggle="collapse" data-target=".collapse:not(.show)" aria-expanded="false">Expand all</button>
            <button class="btn btn-primary" type="button" data-toggle="collapse" data-target=".collapse.show" aria-expanded="false">Collapse all</button>
        </div>
    {%- endif -%}
    {%- if schema.get("type") == "object" and (properties or patternProperties)-%}
        {%- set description = schema.get("description") -%}
        {%- if description -%}
            <span class="description">{{ description | markdown }}</span>
        {%- endif -%}
        {%- set required_properties = schema.get("required") or [] -%}
        {%- if properties -%}
            {%- for property_name, property in properties.items() -%}
                {{ subsection(False, loop.index, "", property_name, property, required_properties, schema_path, True) }}
            {%- endfor -%}
        {%- endif -%}
        {%- if patternProperties -%}
            {%- for property_name, property in patternProperties.items() -%}
                {{ subsection(False, loop.index, "", property_name, property, required_properties, schema_path, False) }}
            {%- endfor -%}
        {%- endif -%}
    {% else %}
        {{ content(0, schema.get("title", "Main schema"), schema, schema_path, False) }}
    {%- endif -%}
</body>
</html>