<?php

namespace Drupal\crop\Form;

use Drupal\Core\Entity\EntityForm;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Link;
use Symfony\Component\Validator\ConstraintViolationListInterface;

/**
 * Form controller for crop type forms.
 */
class CropTypeForm extends EntityForm {

  /**
   * {@inheritdoc}
   */
  public function form(array $form, FormStateInterface $form_state) {
    $form = parent::form($form, $form_state);

    $type = $this->entity;
    $form['#title'] = $this->operation == 'add' ? $this->t('Add crop type')
        :
        $this->t('Edit %label crop type', ['%label' => $type->label()]);

    $form['label'] = [
      '#title' => $this->t('Name'),
      '#type' => 'textfield',
      '#default_value' => $type->label,
      '#description' => $this->t('The human-readable name of this crop type. This name must be unique.'),
      '#required' => TRUE,
      '#size' => 30,
    ];

    $form['id'] = [
      '#type' => 'machine_name',
      '#default_value' => $type->id(),
      '#machine_name' => [
        'exists' => ['\Drupal\crop\Entity\CropType', 'load'],
        'source' => ['label'],
      ],
      // A crop type's machine name cannot be changed.
      '#disabled' => !$type->isNew(),
      '#description' => $this->t('A unique machine-readable name for this crop type. It must only contain lowercase letters, numbers, and underscores.'),
    ];

    $form['description'] = [
      '#title' => $this->t('Description'),
      '#type' => 'textarea',
      '#default_value' => $type->description,
      '#description' => $this->t('Describe this crop type.'),
    ];

    $form['aspect_ratio'] = [
      '#title' => $this->t('Aspect Ratio'),
      '#type' => 'textfield',
      '#default_value' => $type->aspect_ratio,
      '#attributes' => ['placeholder' => 'W:H'],
      '#description' => $this->t('Set an aspect ratio <b>eg: 16:9</b> or leave this empty for arbitrary aspect ratio'),
    ];

    $form['soft_limit'] = [
      '#type' => 'fieldset',
      '#title' => $this->t('Soft limit'),
      '#description' => $this->t('Define crop size soft limit. Warning will be displayed if crop smaller than that is selected.'),
    ];

    $form['soft_limit']['soft_limit_width'] = [
      '#type' => 'number',
      '#title' => $this->t('Width'),
      '#default_value' => $type->soft_limit_width,
      '#description' => $this->t('Limit for width.'),
      '#size' => 60,
      '#field_suffix' => 'px',
      '#min' => 0,
    ];
    $form['soft_limit']['soft_limit_height'] = [
      '#type' => 'number',
      '#title' => $this->t('Height'),
      '#default_value' => $type->soft_limit_height,
      '#description' => $this->t('Limit for height.'),
      '#size' => 60,
      '#field_suffix' => 'px',
      '#min' => 0,
    ];

    $form['hard_limit'] = [
      '#type' => 'fieldset',
      '#title' => $this->t('Hard limit'),
      '#description' => $this->t('Define crop size hard limit. User is not allowed to make a smaller selection than defined here.'),
    ];

    $form['hard_limit']['hard_limit_width'] = [
      '#type' => 'number',
      '#title' => $this->t('Width'),
      '#default_value' => $type->hard_limit_width,
      '#description' => $this->t('Limit for width'),
      '#size' => 60,
      '#field_suffix' => 'px',
      '#min' => 0,
    ];
    $form['hard_limit']['hard_limit_height'] = [
      '#type' => 'number',
      '#title' => $this->t('Height'),
      '#default_value' => $type->hard_limit_height,
      '#description' => $this->t('Limit for height.'),
      '#size' => 60,
      '#field_suffix' => 'px',
      '#min' => 0,
    ];

    return $form;
  }

  /**
   * {@inheritdoc}
   */
  protected function actions(array $form, FormStateInterface $form_state) {
    $actions = parent::actions($form, $form_state);
    $actions['submit']['#value'] = $this->t('Save crop type');
    $actions['delete']['#value'] = $this->t('Delete crop type');
    return $actions;
  }

  /**
   * {@inheritdoc}
   */
  public function validateForm(array &$form, FormStateInterface $form_state) {
    parent::validateForm($form, $form_state);

    /** @var \Drupal\crop\Entity\CropType $entity */
    $entity = $this->buildEntity($form, $form_state);
    $violations = $entity->validate();

    $this->flagViolations($violations, $form, $form_state);
  }

  /**
   * Flags violations for the current form.
   *
   * @param \Symfony\Component\Validator\ConstraintViolationListInterface $violations
   *   The violations to flag.
   * @param array $form
   *   A nested array of form elements comprising the form.
   * @param \Drupal\Core\Form\FormStateInterface $form_state
   *   The current state of the form.
   */
  protected function flagViolations(ConstraintViolationListInterface $violations, array $form, FormStateInterface $form_state) {
    // Manually flag violations of fields not handled by the form display.
    foreach ($violations->getIterator() as $violation) {
      if ($violation->getPropertyPath() == 'aspect_ratio') {
        $form_state->setErrorByName('aspect_ratio', $violation->getMessage());
      }
      if ($violation->getPropertyPath() == 'id') {
        $form_state->setErrorByName('id', $violation->getMessage());
      }
    }
  }

  /**
   * {@inheritdoc}
   */
  public function save(array $form, FormStateInterface $form_state) {
    $type = $this->entity;
    $type->id = trim($type->id());
    $type->label = trim($type->label);
    $type->aspect_ratio = trim($type->aspect_ratio);

    $status = $type->save();

    $t_args = ['%name' => $type->label()];

    if ($status == SAVED_UPDATED) {
      $this->messenger()->addMessage($this->t('The crop type %name has been updated.', $t_args));
    }
    elseif ($status == SAVED_NEW) {
      $this->messenger()->addMessage($this->t('The crop type %name has been added.', $t_args));
      $context = array_merge($t_args, ['link' => Link::createFromRoute($this->t('View'), 'crop.overview_types')->toString()]);
      $this->logger('crop')->notice('Added crop type %name.', $context);
    }

    return $form_state->setRedirect('crop.overview_types');
  }

}
