<?php

namespace Drupal\castorcito\Plugin\CastorcitoComponentField;

use Drupal\Core\Form\FormStateInterface;
use Drupal\castorcito\ConfigurableComponentFieldBase;
use Drupal\Core\Url;
use Drupal\Component\Serialization\Json;

/**
 * List Text configuration.
 *
 * @CastorcitoComponentField(
 *   id = "list_text",
 *   label = @Translation("List text"),
 *   description = @Translation("Configuration for the list text field.")
 * )
 */
class ListText extends ConfigurableComponentFieldBase {

  /**
   * {@inheritdoc}
   */
  public function defaultModel() {
    return [
      'value' => '',
    ];
  }

  /**
   * {@inheritdoc}
   */
  public function defaultConfiguration() {
    return parent::defaultConfiguration() + [
      'options' => [],
      'condition' => FALSE,
      'conditions' => [],
      'set_default_value' => 0,
      'default_value' => '',
    ];
  }

  /**
   * {@inheritdoc}
   */
  public function buildConfigurationForm(array $form, FormStateInterface $form_state) {
    if (!$form_state->get('allowed_values_data')) {
      $form_state->set('allowed_values_data', [
        'options' => $this->configuration['options'],
        'condition' => $this->configuration['condition'],
        'conditions' => $this->configuration['conditions'],
      ]);
    }

    $allowed_values_data = $form_state->get('allowed_values_data');
    $form['allowed_values_data'] = [
      '#type' => 'hidden',
      '#value' => Json::encode($allowed_values_data),
      '#attributes' => ['id' => 'cc-allowed-values-data-hidden'],
    ];

    $options_summary = [];
    foreach ($allowed_values_data['options'] as $option) {
      $options_summary[] = $option['label'] . ' <small>(' . $option['key'] . ')</small>';
    }
    $allowed_values_summary =  $options_summary ? '<ul><li>' . implode('</li><li>', $options_summary) . '</li></ul>' : '';
    $form['allowed_values'] = [
      '#type' => 'details',
      '#title' => $this->t('Allowed values'),
      '#open' => TRUE,
      'list' => [
        '#markup' => '<div class="allowed-values-summary">' . $allowed_values_summary  . '</div>',
      ],
    ];

    $form['allowed_values']['add'] = [
      '#type' => 'link',
      '#title' => $this->t('Add/Edit allowed values'),
      '#url' => Url::fromRoute('castorcito.field_list_text_allowed_value_form')->setRouteParameters([
        'component_id' => $this->component->id(),
        'field_name' => $this->routeMatch->getParameter('field_type')
      ]),
      '#attributes' => [
        'class' => ['button'],
        'id' => 'cc-allowed-values-modal',
      ],
    ];

    $form['update_values'] = [
      '#type' => 'submit',
      '#value' => $this->t('Update values'),
      '#submit' => [
        [$this, 'updateValuesSubmit'],
      ],
      '#limit_validation_errors' => [],
      '#ajax' => [
        'callback' => [$this, 'setDefaultValueCallback'],
        'wrapper' => 'default-value-wrapper',
      ],
      '#attributes' => [
        'class' => ['js-hide', 'update-values-submit'],
      ],
      '#weight' => 100,
    ];

    $form['default_value_wrapper'] = [
      '#type' => 'container',
      '#attributes' => ['id' => 'default-value-wrapper'],
    ];

    $form['default_value_wrapper']['set_default_value'] = [
      '#type' => 'checkbox',
      '#title' => $this->t('Set default value'),
      '#default_value' => $this->configuration['set_default_value'],
      '#description' => $this->t('Provide a pre-filled value for the editing form.'),
    ];

    if (!$form_state->get('default_options')) {
      $configuration_options = [];
      foreach ($this->configuration['options'] as $value) {
        $configuration_options[$value['key']] = $value['label'];
      }
      $form_state->set('default_options', $configuration_options);
    }
    $default_options = $form_state->get('default_options');
    $form['default_value_wrapper']['default_value'] = [
      '#type' => 'select',
      '#title' => $this->t('Default value'),
      '#default_value' => $this->configuration['default_value'],
      '#limit_validation_errors' => [],
      '#options' => $default_options,
      '#states'   => [
        'visible' => [
          ':input[name="settings[default_value_wrapper][set_default_value]"]' => ['checked' => TRUE],
        ],
      ],
    ];

    $form['#attached']['library'][] = 'core/drupal.dialog.ajax';
    $form['#attached']['library'][] = 'castorcito/castorcito.field.list_text';

    return $form;
  }

  /**
   * {@inheritdoc}
   */
  public function validateConfigurationForm(array &$form, FormStateInterface $form_state) {
    $allowed_values = Json::decode($form_state->getValue('allowed_values_data'));
    if (empty($allowed_values['options'])) {
      $form_state->setErrorByName('settings[allowed_values_data]', $this->t('You need to define allowed values before saving.'));
    }
  }

  /**
   * {@inheritdoc}
   */
  public function submitConfigurationForm(array &$form, FormStateInterface $form_state) {
    $allowed_values = Json::decode($form_state->getValue('allowed_values_data'));
    $this->configuration['options'] = $allowed_values['options'];
    $this->configuration['condition'] = $allowed_values['condition'];
    $this->configuration['set_default_value'] = $form_state->getValue(['default_value_wrapper', 'set_default_value']);
    $this->configuration['default_value'] = $form_state->getValue(['default_value_wrapper', 'default_value']);

    if ($allowed_values['condition']) {
      $this->configuration['conditions'] = $allowed_values['conditions'];
    }
    else {
      if (isset($this->configuration['conditions'])) {
        unset($this->configuration['conditions']);
      }
    }
  }

  /**
   * Ajax callback for the "Add another item" button.
   */
  public function setDefaultValueCallback(array &$form, FormStateInterface $form_state) {
    return $form['settings']['default_value_wrapper'];
  }

  /**
   * Update default values.
   *
   * @param array $form
   *   The form array to add elements to.
   * @param \Drupal\Core\Form\FormStateInterface $form_state
   *   The current state of the form.
   */
  public function updateValuesSubmit(array &$form, FormStateInterface $form_state) {
    $allowed_values_data =  Json::decode($form_state->getUserInput()['settings']['allowed_values_data']);
    $form_state->set('allowed_values_data', $allowed_values_data);
    $form_state->set('default_options', array_column($allowed_values_data['options'], 'label', 'key'));
    $form_state->setRebuild();
  }

}
