<?php

declare(strict_types=1);

namespace Drupal\sobki_tablefield\Plugin\Field\FieldFormatter;

use Drupal\Core\Field\FieldItemListInterface;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
use Drupal\ui_patterns\Form\PatternDisplayFormTrait;
use Drupal\ui_patterns_field_formatters\Plugin\Field\FieldFormatter\PatternOneForAllFormatter;

/**
 * Plugin implementation of the Sobki Tablefield formatter.
 *
 * @FieldFormatter(
 *     id = "sobki_tablefield",
 *     label = @Translation("Sobki Tabular View"),
 *     field_types = {
 *         "tablefield"
 *     }
 * )
 */
class SobkiTablefieldFormatter extends PatternOneForAllFormatter implements ContainerFactoryPluginInterface {

  use PatternDisplayFormTrait;

  /**
   * {@inheritdoc}
   */
  public static function defaultSettings() {
    $settings = parent::defaultSettings();
    $settings['row_header'] = 1;
    return $settings;
  }

  /**
   * {@inheritdoc}
   */
  public function settingsForm(array $form, FormStateInterface $form_state) {
    // Prevent nesting (unsupported yet).
    unset($form['type']['#options']['pattern_all_formatter'], $form['type']['#options']['pattern_each_formatter']);

    $form['row_header'] = [
      '#type' => 'checkbox',
      '#title' => $this->t('Display first row as a table header'),
      '#default_value' => $this->getSetting('row_header'),
    ];

    $field_storage_definition = $this->fieldDefinition->getFieldStorageDefinition();
    $context = [
      'storageDefinition' => $field_storage_definition,
      'limit' => $field_storage_definition->getPropertyNames(),
    ];

    // Some modifications to make 'variant' default value working.
    $configuration = $this->getSettings();

    $this->buildPatternDisplayForm($form, 'field_properties', $context, $configuration);

    $form['pattern']['#default_value'] = 'table';
    $form['pattern']['#attributes']['disabled'] = 'disabled';
    $form['#element_validate'] = [[static::class, 'cleanSettings']];
    return $form;
  }

  /**
   * {@inheritdoc}
   */
  public function settingsSummary() {
    $summary = parent::settingsSummary();

    $row_header = $this->getSetting('row_header');
    if ($row_header) {
      $summary[] = (string) $this->t('First row as a table header');
    }

    return $summary;
  }

  /**
   * {@inheritdoc}
   *
   * @SuppressWarnings(PHPMD.CyclomaticComplexity)
   * @SuppressWarnings(PHPMD.NPathComplexity)
   */
  public function viewElements(FieldItemListInterface $items, $langcode = NULL) {
    $entity = $items->getEntity();
    $elements = [];
    $row_header = $this->getSetting('row_header');
    $pattern = $this->getSetting('pattern');
    /** @var string $pattern_variant */
    $pattern_variant = $this->getSetting('pattern_variant');
    /** @var array $settings */
    $settings = $this->getSetting('pattern_settings');
    $pattern_settings = !empty($settings) && isset($settings[$pattern]) ? $settings[$pattern] : NULL;
    /** @var array $variant_tokens */
    $variant_tokens = $this->getSetting('variants_token');
    $variant_token = !empty($variant_tokens) && isset($variant_tokens[$pattern]) ? $variant_tokens[$pattern] : NULL;

    foreach ($items as $item) {
      if (empty($item->value)) {
        continue;
      }

      $header = [];
      $rows = [];
      $table_data = $item->value;

      $caption = $table_data['caption'] ?? '';
      unset($table_data['caption']);

      // Prepare rows.
      foreach ($table_data as $row_key => $row_data) {
        $cells = [];
        foreach ($row_data as $col_key => $cell) {
          if (!\is_numeric($col_key)) {
            continue;
          }

          $cells[$col_key] = [
            '#type' => 'pattern',
            '#id' => 'table_cell',
            '#content' => empty($item->format) ? $cell : \check_markup($cell, $item->format),
          ];
        }

        $rows[$row_key] = [
          '#type' => 'pattern',
          '#id' => 'table_row',
          '#cells' => $cells,
        ];
      }

      if ($row_header) {
        // Pull the header for theming.
        $header_row = \array_shift($rows);
        if (\is_array($header_row)) {
          $header = $header_row['#cells'];

          foreach ($header as $key => $cell) {
            $header[$key]['#tag'] = 'th';
          }
        }
      }

      // Set pattern render array.
      $table = [
        '#type' => 'pattern',
        '#id' => $pattern,
        '#context' => [
          'entity' => $entity,
          'type' => 'field_formatter',
          'formatter' => [
            'id' => $this->getPluginId(),
            'class' => static::class,
          ],
          'items' => $items,
          'item' => $item,
        ],
        '#fields' => [
          'caption' => $caption,
          'header' => $header,
          'rows' => $rows,
        ],
      ];

      // Set the variant.
      if (!empty($pattern_variant)) {
        $table['#variant'] = $pattern_variant;
      }
      // Set the settings.
      if (!empty($pattern_settings)) {
        $table['#settings'] = $pattern_settings;
      }
      // Set the variant tokens.
      if (!empty($variant_token)) {
        $table['#variant_token'] = $variant_token;
      }

      $elements[] = $table;
    }

    return $elements;
  }

}
