<?php declare(strict_types = 1);

namespace Drupal\{{ machine_name }}\Plugin\Field\FieldWidget;

{% sort %}
  {% if datetime %}
use Drupal\Core\Datetime\DrupalDateTime;
  {% endif %}
use Drupal\Core\Field\FieldItemListInterface;
use Drupal\Core\Field\WidgetBase;
use Drupal\Core\Form\FormStateInterface;
use Symfony\Component\Validator\ConstraintViolationInterface;
  {% if list %}
use Drupal\{{ machine_name }}\Plugin\Field\FieldType\{{ type_class }};
  {% endif %}
{% endsort %}

/**
 * Defines the '{{ field_id }}' field widget.
 *
 * @FieldWidget(
 *   id = "{{ field_id }}",
 *   label = @Translation("{{ field_label }}"),
 *   field_types = {"{{ field_id }}"},
 * )
 */
final class {{ widget_class }} extends WidgetBase {

{% if widget_settings %}
  /**
   * {@inheritdoc}
   */
  public static function defaultSettings(): array {
    return ['foo' => 'bar'] + parent::defaultSettings();
  }

  /**
   * {@inheritdoc}
   */
  public function settingsForm(array $form, FormStateInterface $form_state): array {
    $element['foo'] = [
      '#type' => 'textfield',
      '#title' => $this->t('Foo'),
      '#default_value' => $this->getSetting('foo'),
    ];
    return $element;
  }

  /**
   * {@inheritdoc}
   */
  public function settingsSummary(): array {
    return [
      $this->t('Foo: @foo', ['@foo' => $this->getSetting('foo')]),
    ];
  }

{% endif %}
  /**
   * {@inheritdoc}
   */
  public function formElement(FieldItemListInterface $items, $delta, array $element, array &$form, FormStateInterface $form_state): array {

{% for subfield in subfields %}
  {% if subfield.list %}
    $element['{{ subfield.machine_name }}'] = [
      '#type' => 'select',
      '#title' => $this->t('{{ subfield.name }}'),
      '#options' => ['' => $this->t('- {{ subfield.required ? 'Select a value' : 'None' }} -')] + {{ type_class }}::{{ subfield.allowed_values_method }}(),
      '#default_value' => $items[$delta]->{{ subfield.machine_name }} ?? NULL,
    ];
  {% else %}
    {% if subfield.type == 'boolean' %}
    $element['{{ subfield.machine_name }}'] = [
      '#type' => 'checkbox',
      '#title' => $this->t('{{ subfield.name }}'),
      '#default_value' => $items[$delta]->{{ subfield.machine_name }} ?? NULL,
    ];
    {% elseif subfield.type == 'string' %}
    $element['{{ subfield.machine_name }}'] = [
      '#type' => 'textfield',
      '#title' => $this->t('{{ subfield.name }}'),
      '#default_value' => $items[$delta]->{{ subfield.machine_name }} ?? NULL,
      {% if inline %}
      '#size' => 20,
      {% endif %}
    ];
    {% elseif subfield.type == 'text' %}
    $element['{{ subfield.machine_name }}'] = [
      '#type' => 'textarea',
      '#title' => $this->t('{{ subfield.name }}'),
      '#default_value' => $items[$delta]->{{ subfield.machine_name }} ?? NULL,
    ];
    {% elseif subfield.type == 'integer' %}
    $element['{{ subfield.machine_name }}'] = [
      '#type' => 'number',
      '#title' => $this->t('{{ subfield.name }}'),
      '#default_value' => $items[$delta]->{{ subfield.machine_name }} ?? NULL,
    ];
    {% elseif subfield.type == 'float' %}
    $element['{{ subfield.machine_name }}'] = [
      '#type' => 'number',
      '#title' => $this->t('{{ subfield.name }}'),
      '#default_value' => $items[$delta]->{{ subfield.machine_name }} ?? NULL,
      '#step' => 0.001,
    ];
    {% elseif subfield.type == 'numeric' %}
    $element['{{ subfield.machine_name }}'] = [
      '#type' => 'number',
      '#title' => $this->t('{{ subfield.name }}'),
      '#default_value' => $items[$delta]->{{ subfield.machine_name }} ?? NULL,
      '#step' => 0.01,
    ];
    {% elseif subfield.type == 'email' %}
    $element['{{ subfield.machine_name }}'] = [
      '#type' => 'email',
      '#title' => $this->t('{{ subfield.name }}'),
      '#default_value' => $items[$delta]->{{ subfield.machine_name }} ?? NULL,
      {% if inline %}
      '#size' => 20,
      {% endif %}
    ];
    {% elseif subfield.type == 'telephone' %}
    $element['{{ subfield.machine_name }}'] = [
      '#type' => 'tel',
      '#title' => $this->t('{{ subfield.name }}'),
      '#default_value' => $items[$delta]->{{ subfield.machine_name }} ?? NULL,
      {% if inline %}
      '#size' => 20,
      {% endif %}
    ];
    {% elseif subfield.type == 'uri' %}
    $element['{{ subfield.machine_name }}'] = [
      '#type' => 'url',
      '#title' => $this->t('{{ subfield.name }}'),
      '#default_value' => $items[$delta]->{{ subfield.machine_name }} ?? NULL,
      {% if inline %}
      '#size' => 20,
      {% endif %}
    ];
    {% elseif subfield.type == 'datetime' %}
    $element['{{ subfield.machine_name }}'] = [
      '#type' => 'datetime',
      '#title' => $this->t('{{ subfield.name }}'),
      '#default_value' => NULL,
      {% if subfield.date_type == 'date' %}
      '#date_time_element' => 'none',
      '#date_time_format' => '',
      {% endif %}
    ];
    if (isset($items[$delta]->{{ subfield.machine_name }})) {
      $element['{{ subfield.machine_name }}']['#default_value'] = DrupalDateTime::createFromFormat(
        '{{ subfield.date_storage_format }}',
        $items[$delta]->{{ subfield.machine_name }},
        'UTC'
      );
    }
    {% endif %}
  {% endif %}

{% endfor %}
    $element['#theme_wrappers'] = ['container', 'form_element'];
{% if inline %}
    $element['#attributes']['class'][] = 'container-inline';
{% endif %}
    $element['#attributes']['class'][] = '{{ field_id|u2h }}-elements';
    $element['#attached']['library'][] = '{{ machine_name }}/{{ field_id }}';

    return $element;
  }

  /**
   * {@inheritdoc}
   */
  public function errorElement(array $element, ConstraintViolationInterface $error, array $form, FormStateInterface $form_state): array|bool {
    $element = parent::errorElement($element, $error, $form, $form_state);
    if ($element === FALSE) {
      return FALSE;
    }
    $error_property = explode('.', $error->getPropertyPath())[1];
    return $element[$error_property];
  }

  /**
   * {@inheritdoc}
   */
  public function massageFormValues(array $values, array $form, FormStateInterface $form_state): array {
    foreach ($values as $delta => $value) {
{% for subfield in subfields %}
      if ($value['{{ subfield.machine_name }}'] === '') {
        $values[$delta]['{{ subfield.machine_name }}'] = NULL;
      }
  {% if subfield.type == 'datetime' %}
      if ($value['{{ subfield.machine_name }}'] instanceof DrupalDateTime) {
        $values[$delta]['{{ subfield.machine_name }}'] = $value['{{ subfield.machine_name }}']->format('{{ subfield.date_storage_format }}');
      }
  {% endif %}
{% endfor %}
    }
    return $values;
  }

}
