{% from "nhsuk/components/error-message/macro.njk" import errorMessage as nhsukErrorMessage %}
{% from "nhsuk/components/fieldset/macro.njk" import fieldset as nhsukFieldset %}
{% from "nhsuk/components/hint/macro.njk" import hint as nhsukHint %}
{% from "nhsuk/components/label/macro.njk" import label as nhsukLabel %}
{% from "nhsuk/macros/attributes.njk" import nhsukAttributes %}
{% from "nhsuk/macros/content.njk" import nhsukContent %}
{% from "nhsuk/macros/slot.njk" import nhsukSlot %}

{#- Set classes for this component #}
{%- set classNames = "nhsuk-checkboxes" %}
{%- set classNamesFormGroup = "nhsuk-form-group" %}

{#- Support hint as string #}
{%- set hint = params.hint if params.hint is mapping and params.hint is not escaped else {
  text: params.hint if params.hint is string else undefined,
  html: params.hint if params.hint is escaped else undefined
} %}

{#- Support error message as string #}
{%- set errorMessage = params.errorMessage if params.errorMessage is mapping and params.errorMessage is not escaped else {
  text: params.errorMessage if params.errorMessage is string else undefined,
  html: params.errorMessage if params.errorMessage is escaped else undefined
} %}

{%- if params.small and (not params.classes or not "nhsuk-checkboxes--small" in params.classes) %}
  {%- set classNames = classNames ~ " nhsuk-checkboxes--small" %}
{%- endif %}

{%- if params.inline and (not params.classes or not "nhsuk-checkboxes--inline" in params.classes) %}
  {%- set classNames = classNames ~ " nhsuk-checkboxes--inline" %}
{%- endif %}

{%- if errorMessage.text or errorMessage.html or params.errorMessage is sameas(true) %}
  {%- set classNamesFormGroup = classNamesFormGroup ~ " nhsuk-form-group--error" %}
{%- endif %}

{%- if params.classes %}
  {%- set classNames = classNames ~ " " ~ params.classes %}
{%- endif %}

{%- if params.formGroup.classes %}
  {%- set classNamesFormGroup = classNamesFormGroup ~ " " ~ params.formGroup.classes %}
{%- endif %}

{%- set items = params.items | select("mapping") | list if params.items else [] %}

{#- If an id 'prefix' is not passed, fall back to using the name attribute
  instead. We need this for error messages and hints as well #}
{%- set idPrefix = params.idPrefix if params.idPrefix else params.name %}

{#- a record of other elements that we need to associate with the input using
  aria-describedby – for example hints or error messages #}
{%- set describedBy = params.describedBy if params.describedBy else "" %}
{%- if params.fieldset.describedBy %}
  {%- set describedBy = params.fieldset.describedBy %}
{%- endif %}

{#- fieldset is false by default #}
{%- set hasFieldset = true if params.fieldset else false %}

{%- macro _checkboxItem(item, parent) %}
  {#- Support item label as string #}
  {%- set itemLabel = item.label if item.label is mapping and item.label is not escaped else {
    text: item.label if item.label is string else undefined,
    html: item.label if item.label is escaped else undefined
  } %}

  {#- Support item hint as string #}
  {%- set itemHint = item.hint if item.hint is mapping and item.hint is not escaped else {
    text: item.hint if item.hint is string else undefined,
    html: item.hint if item.hint is escaped else undefined
  } %}

  {#- Support item conditional content as string #}
  {%- set itemConditional = item.conditional if item.conditional is mapping and item.conditional is not escaped else {
    text: item.conditional if item.conditional is string else undefined,
    html: item.conditional if item.conditional is escaped else undefined
  } %}

  {#- If the user explicitly sets an id, use this instead of the regular idPrefix #}
  {#- The first id should not have a number suffix so it's easy to link to from the error summary component #}
  {%- set itemId = item.id if item.id else parent.idPrefix ~ ("-" ~ parent.loop.index if parent.loop.index > 1 else "") %}
  {%- set itemName = item.name if item.name else parent.params.name %}
  {%- set conditionalId = "conditional-" ~ itemId %}
  {%- if item.divider %}
    <div class="nhsuk-checkboxes__divider {{- " nhsuk-u-frontend-not-supported-hidden" if item.behaviour == "inclusive" else "" }}">
      {{- nhsukContent(item.divider) | trim | indent(4) -}}
    </div>
  {% else %}
    {%- set isChecked = item.checked | default((item.value in parent.params.values and item.checked is not sameas(false)) if parent.params.values else false, true) %}
    {%- set hasHint = true if itemHint.text or itemHint.html %}
    {%- set itemHintId = itemHint.id | default(itemId ~ "-item-hint") if hasHint else "" %}
    {%- set itemDescribedBy = parent.describedBy if not parent.hasFieldset else "" %}
    {%- set itemDescribedBy = (itemDescribedBy ~ " " ~ itemHintId) | trim %}
    {%- set itemClasses = "nhsuk-checkboxes__input" ~ (" " ~ item.classes if item.classes) %}
    {#- The item.exclusive option is deprecated, to be removed in v11.0 #}
    {%- set itemBehaviour = "exclusive" if item.exclusive else item.behaviour %}
    {#- The item.exclusiveGroup option is deprecated, to be removed in v11.0 #}
    {%- set itemBehaviourGroup = item.exclusiveGroup | default(item.behaviourGroup) %}
    <div class="nhsuk-checkboxes__item {{- " nhsuk-u-frontend-not-supported-hidden" if item.behaviour == "inclusive" else "" }}">
      <input class="{{ itemClasses }}" id="{{ itemId }}" name="{{ itemName }}" type="checkbox" value="{{ item.value }}"
        {{- " checked" if isChecked }}
        {{- " disabled" if item.disabled or (item.disabled is not sameas(false) and parent.params.disabled) }}
        {%- if itemBehaviour %} data-behaviour="{{ itemBehaviour }}"{% endif %}
        {%- if itemBehaviourGroup %} data-behaviour-group="{{ itemBehaviourGroup }}"{% endif %}
        {%- if itemConditional.html or itemConditional.text %} data-aria-controls="{{ conditionalId }}"{% endif %}
        {%- if itemDescribedBy %} aria-describedby="{{ itemDescribedBy }}"{% endif %}
        {{- nhsukAttributes(item.attributes) }}>
      {{ nhsukLabel({
        html: itemLabel.html | default(item.html),
        text: itemLabel.text | default(item.text),
        visuallyHiddenText: itemLabel.visuallyHiddenText,
        id: itemLabel.id,
        for: itemId,
        classes: "nhsuk-checkboxes__label" ~ (" " ~ itemLabel.classes if itemLabel.classes),
        attributes: itemLabel.attributes
      }) | trim | indent(6) }}
      {% if hasHint %}
      {{ nhsukHint({
        html: itemHint.html,
        text: itemHint.text,
        id: itemHint.id | default(itemHintId),
        classes: "nhsuk-checkboxes__hint" ~ (" " ~ itemHint.classes if itemHint.classes),
        attributes: itemHint.attributes
      }) | trim | indent(6) }}
      {% endif %}
    </div>
    {% if itemConditional.html or itemConditional.text %}
    <div class="nhsuk-checkboxes__conditional {%- if not isChecked %} nhsuk-checkboxes__conditional--hidden{% endif %}" id="{{ conditionalId }}">
    {% if itemConditional.html %}
      {{- nhsukContent({ html: itemConditional.html }) | trim }}
    {% else %}
      <p>{{ nhsukContent({ text: itemConditional.text }) | trim | indent(6) }}</p>
    {% endif %}
    </div>
    {% endif %}
  {% endif %}
{%- endmacro %}

{%- macro _checkboxItems(items, parent) %}
{%- set beforeInputsSlotHtml = nhsukSlot("beforeInputs", parent) | trim %}
{%- set afterInputsSlotHtml = nhsukSlot("afterInputs", parent) | trim %}

{%- if beforeInputsSlotHtml | length %}
  {{- beforeInputsSlotHtml | indent(4, true) -}}
  {{- "\n" | safe -}}
{% endif %}

{%- for item in items %}
  {{- _checkboxItem(item, {
    params: parent.params,
    idPrefix: parent.idPrefix,
    describedBy: parent.describedBy,
    hasFieldset: parent.hasFieldset,
    loop: loop
  }) }}
{%- endfor %}

{%- if afterInputsSlotHtml | length %}
  {{- afterInputsSlotHtml | indent(4, true) -}}
{% endif %}
{% endmacro %}

{#- Capture the HTML so we can optionally nest it in a fieldset #}
{%- set innerHtml %}
{%- if hint.text or hint.html %}
  {%- set hintId = hint.id | default(idPrefix ~ "-hint") %}
  {%- set describedBy = (describedBy ~ " " ~ hintId) | trim %}
  {{ nhsukHint({
    html: hint.html,
    text: hint.text,
    id: hint.id | default(hintId),
    classes: hint.classes,
    attributes: hint.attributes
  }) | trim | indent(2) }}
{% endif %}
{% if errorMessage.text or errorMessage.html %}
  {%- set errorId = errorMessage.id | default(idPrefix ~ "-error") %}
  {%- set describedBy = (describedBy ~ " " ~ errorId) | trim %}
  {{ nhsukErrorMessage({
    html: errorMessage.html,
    text: errorMessage.text,
    visuallyHiddenText: errorMessage.visuallyHiddenText,
    id: errorMessage.id | default(errorId),
    classes: errorMessage.classes,
    attributes: errorMessage.attributes
  }) | trim | indent(2) }}
{% endif %}
  <div
    {{- nhsukAttributes({
      class: classNames,
      id: {
        value: params.id,
        optional: true
      },
      "data-module": "nhsuk-checkboxes"
    }) -}}

    {{- nhsukAttributes(params.attributes) }}>
    {{ _checkboxItems(items, {
      params: params,
      slots: params.formGroup,
      idPrefix: idPrefix,
      describedBy: describedBy,
      hasFieldset: hasFieldset
    }) | trim }}
  </div>
{%- endset -%}

<div class="{{ classNamesFormGroup }}" {{- nhsukAttributes(params.formGroup.attributes) }}>
{% if hasFieldset %}
  {{ nhsukFieldset({
    legend: params.fieldset.legend,
    html: innerHtml,
    id: params.fieldset.id,
    role: params.fieldset.role,
    describedBy: describedBy,
    classes: params.fieldset.classes,
    attributes: params.fieldset.attributes
  }) | trim }}
{% else %}
  {{- innerHtml | safe }}
{% endif %}
</div>
