<?php

namespace Drupal\component_builder_toolbar\Form;

use Drupal\Component\Datetime\TimeInterface;
use Drupal\component_builder\ComponentBuilderManager;
use Drupal\component_builder\Form\ComponentWrapperForm;
use Drupal\component_builder_toolbar\ToolbarManagerInterface;
use Drupal\Core\Ajax\AjaxResponse;
use Drupal\Core\Ajax\AppendCommand;
use Drupal\Core\Ajax\BaseCommand;
use Drupal\Core\Ajax\CloseDialogCommand;
use Drupal\Core\Ajax\InvokeCommand;
use Drupal\Core\Ajax\ReplaceCommand;
use Drupal\Core\Cache\Cache;
use Drupal\Core\Entity\EntityRepositoryInterface;
use Drupal\Core\Entity\EntityTypeBundleInfoInterface;
use Drupal\Core\Extension\ExtensionPathResolver;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Url;
use Symfony\Component\DependencyInjection\ContainerInterface;

/**
 * Provide form to add component for toolbar.
 */
class ToolbarComponentWrapperForm extends ComponentWrapperForm {

  /**
   * The toolbar manager interface.
   *
   * @var \Drupal\component_builder_toolbar\ToolbarManagerInterface
   */
  protected $toolbarManager;

  /**
   * Constructs a ContentEntityForm object.
   *
   * @param \Drupal\Core\Entity\EntityRepositoryInterface $entity_repository
   *   The entity repository service.
   * @param \Drupal\Core\Entity\EntityTypeBundleInfoInterface $entity_type_bundle_info
   *   The entity type bundle service.
   * @param \Drupal\Component\Datetime\TimeInterface $time
   *   The time service.
   * @param \Drupal\Core\Extension\ExtensionPathResolver $extension_path_resolver
   *   The extension path resolver.
   * @param \Drupal\component_builder_toolbar\ToolbarManagerInterface $toolbar_manager
   *   The toolbar manager interface.
   * @param \Drupal\component_builder\ComponentBuilderManager $component_builder_manager
   *   The component builder plugin manager.
   */
  public function __construct(EntityRepositoryInterface $entity_repository, EntityTypeBundleInfoInterface $entity_type_bundle_info, TimeInterface $time, ExtensionPathResolver $extension_path_resolver, ToolbarManagerInterface $toolbar_manager, ComponentBuilderManager $component_builder_manager) {
    parent::__construct($entity_repository, $entity_type_bundle_info, $time, $extension_path_resolver, $component_builder_manager);
    $this->toolbarManager = $toolbar_manager;
  }

  /**
   * {@inheritdoc}
   */
  public static function create(ContainerInterface $container) {
    return new static(
      $container->get('entity.repository'),
      $container->get('entity_type.bundle.info'),
      $container->get('datetime.time'),
      $container->get('extension.path.resolver'),
      $container->get('component_builder_toolbar.manager'),
      $container->get('plugin.manager.component_builder'),
    );
  }

  /**
   * {@inheritdoc}
   */
  public function buildForm(array $form, FormStateInterface $form_state) {
    $form = parent::buildForm($form, $form_state);
    unset($form['revision']);
    return $form;
  }

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

    if (isset($actions['delete'])) {
      unset($actions['delete']);
    }

    $actions['submit']['#ajax'] = [
      'callback' => [$this, 'toolbarFormAjaxSubmit'],
    ];

    $actions['cancel'] = [
      '#type' => 'submit',
      '#value' => $this->t('Cancel'),
      '#ajax' => [
        'callback' => [$this, 'cancelForm'],
      ],
    ];

    return $actions;
  }

  /**
   * {@inheritdoc}
   */
  public function save(array $form, FormStateInterface $form_state) {
    $component_wrapper = $this->getEntity();
    $component_wrapper->save();

    if ($form_state->get('is_ajax')) {
      if ($form_state->get('toolbar_form_mode') == 'add') {
        $current_entity = $form_state->get('current_entity');
        $field_name = $form_state->get('field_name');

        try {
          $delta = count($current_entity->{$field_name});
          $current_entity->{$field_name}[] = $component_wrapper->id();
          $current_entity->save();
          $form_state->set('delta', $delta);
          $form_state->set('component_wrapper', $component_wrapper);
        }
        catch (\Exception $e) {
          $form_state->set('add_component_wrapper_error', $e->getMessage());
        }
      }

      $form_state->disableRedirect(TRUE);
    }
  }

  /**
   * Ajax callback function.
   */
  public function toolbarFormAjaxSubmit(array $form, FormStateInterface $form_state) {
    $response = new AjaxResponse();

    /** @var \Drupal\component_builder\Entity\ComponentWrapperInterface $component_wrapper */
    $component_wrapper = $form_state->get('component_wrapper') ?? $this->getEntity();
    $entity_type_id = $form_state->get('entity_type_id');
    $field_name = $form_state->get('field_name');
    $current_entity = $form_state->get('current_entity');

    $move_wrapper_url = Url::fromRoute(
      'entity.' . $entity_type_id . '.component_builder_toolbar_move_component',
      [
        $entity_type_id => $current_entity->id(),
        'component_wrapper' => $component_wrapper->id(),
        'field_name' => $field_name,
      ]
    );

    if ($form_state->get('add_component_wrapper_error')) {
      $response->addCommand(new BaseCommand('error', $form_state->get('add_component_wrapper_error')));
      return $response;
    }
    $delta = $form_state->get('delta');
    $component_wrapper_markup = $this->toolbarManager->buildComponentWrapperMarkup($current_entity, $component_wrapper, $move_wrapper_url, $delta);
    if ($form_state->get('toolbar_form_mode') == 'add') {
      $selector = '.component-builder-toolbar__field .component-builder-toolbar__region';
      $response->addCommand(new AppendCommand($selector, $component_wrapper_markup));
    }
    elseif ($form_state->get('toolbar_form_mode') == 'edit') {
      $selector = '#component-builder-toolbar__wrapper-' . $component_wrapper->id();
      $response->addCommand(new ReplaceCommand($selector, $component_wrapper_markup));
    }

    // Invalid cache tag to rerender component markup again after refreshing
    // the page.
    Cache::invalidateTags([
      'component_builder_toolbar:component_wrapper_field:' . $current_entity->id(),
      'component_builder_toolbar:component_wrapper:' . $current_entity->id() . ':' . $component_wrapper->id(),
    ]);
    $response->addCommand(new CloseDialogCommand());
    $response->addCommand(new InvokeCommand('#component-builder-toolbar__wrapper-' . $component_wrapper->id(), 'componentToolbarScrollTo', []));

    return $response;
  }

  /**
   * Cancel form AJAX callback.
   */
  public function cancelForm(array $form, FormStateInterface $form_state) {
    $response = new AjaxResponse();
    $response->addCommand(new CloseDialogCommand());
    return $response;
  }

}
