<?php

namespace Drupal\nodehive_area_fragment\Form;

use Drupal\Component\Serialization\Json;
use Drupal\Core\Datetime\DateFormatterInterface;
use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Entity\EntityRepositoryInterface;
use Drupal\Core\Entity\EntityTypeBundleInfoInterface;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\Extension\ModuleHandlerInterface;
use Drupal\Core\Form\FormBase;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Language\LanguageManagerInterface;
use Drupal\Core\Render\RendererInterface;
use Drupal\Core\Routing\UrlGeneratorInterface;
use Drupal\Core\StringTranslation\TranslationInterface;
use Drupal\Core\Url;
use Drupal\nodehive_area_fragment\AreaFragmentListBuilderHelperInterface;
use Drupal\nodehive_core\Helper\NodehiveLanguageHelper;
use Drupal\nodehive_core\SpaceInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;

/**
 * Provides a form managing fragments in an area.
 */
class SpaceListBuilderFormBase extends FormBase {

  /**
   * The entity type manager.
   *
   * @var \Drupal\Core\Entity\EntityTypeManagerInterface
   */
  protected $entityTypeManager;

  /**
   * The entity type bundle info.
   *
   * @var \Drupal\Core\Entity\EntityTypeBundleInfoInterface
   */
  protected $entityTypeBundleInfo;

  /**
   * The entity repository.
   *
   * @var \Drupal\Core\Entity\EntityRepositoryInterface
   */
  protected $entityRepository;

  /**
   * The renderer.
   *
   * @var \Drupal\Core\Render\RendererInterface
   */
  protected $renderer;

  /**
   * The URL generator.
   *
   * @var \Drupal\Core\Routing\UrlGeneratorInterface
   */
  protected $urlGenerator;

  /**
   * The date formatter service.
   *
   * @var \Drupal\Core\Datetime\DateFormatterInterface
   */
  protected $dateFormatter;

  /**
   * The list builder helper.
   *
   * @var \Drupal\nodehive_area_fragment\AreaFragmentListBuilderHelperInterface
   */
  protected $listBuilderHelper;

  /**
   * The module_handler service.
   *
   * @var \Drupal\Core\Extension\ModuleHandlerInterface
   */
  protected $moduleHandler;

  /**
   * Language manager.
   *
   * @var \Drupal\Core\Language\LanguageManagerInterface
   */
  protected $languageManager;

  /**
   * The Nodehive language helper.
   *
   * @var \Drupal\nodehive_core\Helper\NodehiveLanguageHelper
   */
  protected $nodehiveLanguageHelper;

  /**
   * Constructs a new EntityController.
   *
   * @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager
   *   The entity type manager.
   * @param \Drupal\Core\Entity\EntityTypeBundleInfoInterface $entity_type_bundle_info
   *   The entity type bundle info.
   * @param \Drupal\Core\Entity\EntityRepositoryInterface $entity_repository
   *   The entity repository.
   * @param \Drupal\Core\Render\RendererInterface $renderer
   *   The renderer.
   * @param \Drupal\Core\StringTranslation\TranslationInterface $string_translation
   *   The string translation.
   * @param \Drupal\Core\Routing\UrlGeneratorInterface $url_generator
   *   The URL generator.
   * @param \Drupal\Core\Datetime\DateFormatterInterface $date_formatter
   *   The date formatter service.
   * @param \Drupal\nodehive_area_fragment\AreaFragmentListBuilderHelperInterface $list_builder_helper
   *   The list builder helper.
   * @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler
   *   The module_handler service.
   * @param \Drupal\Core\Language\LanguageManagerInterface $language_manager
   *   The language manager.
   * @param \Drupal\nodehive_core\Helper\NodehiveLanguageHelper $nodehive_language_helper
   *   The Nodehive language helper.
   */
  public function __construct(
    EntityTypeManagerInterface $entity_type_manager,
    EntityTypeBundleInfoInterface $entity_type_bundle_info,
    EntityRepositoryInterface $entity_repository,
    RendererInterface $renderer,
    TranslationInterface $string_translation,
    UrlGeneratorInterface $url_generator,
    DateFormatterInterface $date_formatter,
    AreaFragmentListBuilderHelperInterface $list_builder_helper,
    ModuleHandlerInterface $module_handler,
    LanguageManagerInterface $language_manager,
    NodehiveLanguageHelper $nodehive_language_helper,
  ) {
    $this->entityTypeManager = $entity_type_manager;
    $this->entityTypeBundleInfo = $entity_type_bundle_info;
    $this->entityRepository = $entity_repository;
    $this->renderer = $renderer;
    $this->stringTranslation = $string_translation;
    $this->urlGenerator = $url_generator;
    $this->dateFormatter = $date_formatter;
    $this->listBuilderHelper = $list_builder_helper;
    $this->moduleHandler = $module_handler;
    $this->languageManager = $language_manager;
    $this->nodehiveLanguageHelper = $nodehive_language_helper;
  }

  /**
   * {@inheritdoc}
   */
  public static function create(ContainerInterface $container) {
    return new static(
      $container->get('entity_type.manager'),
      $container->get('entity_type.bundle.info'),
      $container->get('entity.repository'),
      $container->get('renderer'),
      $container->get('string_translation'),
      $container->get('url_generator'),
      $container->get('date.formatter'),
      $container->get('nodehive_area_fragment.list_builder_helper'),
      $container->get('module_handler'),
      $container->get('language_manager'),
      $container->get('nodehive_core.language_helper'),
    );
  }

  /**
   * {@inheritdoc}
   */
  public function getFormId() {
    return '';
  }

  /**
   * {@inheritdoc}
   */
  public function buildForm(array $form, FormStateInterface $form_state) {
    return $form;
  }

  /**
   * {@inheritdoc}
   */
  public function submitForm(array &$form, FormStateInterface $form_state) {
  }

  /**
   * Build translation links.
   *
   * @param \Drupal\Core\Entity\EntityInterface $entity
   *   The entity.
   *
   * @return array
   *   A renderable array.
   */
  protected function buildTranslationLinks(EntityInterface $entity) {
    // Use the NodehiveLanguageHelper service for consistent language links.
    return $this->nodehiveLanguageHelper->buildLanguageEditLinks($entity);
  }

  /**
   * Builds a renderable list of operation links for the entity.
   *
   * @param \Drupal\Core\Entity\EntityInterface $entity
   *   The entity.
   * @param \Drupal\nodehive_core\SpaceInterface|null $nodehive_space
   *   The space entity.
   *
   * @return array
   *   A renderable array of operation links.
   */
  public function buildOperations(EntityInterface $entity, ?SpaceInterface $nodehive_space = NULL) {
    $build = [
      '#type' => 'operations',
      '#links' => $this->getOperations($entity, $nodehive_space),
      '#attached' => [
        'library' => ['core/drupal.dialog.ajax'],
      ],
    ];

    return $build;
  }

  /**
   * {@inheritdoc}
   */
  public function getOperations(EntityInterface $entity, ?SpaceInterface $nodehive_space = NULL) {
    $operations = $this->getDefaultOperations($entity, $nodehive_space);
    $operations += $this->moduleHandler->invokeAll('entity_operation', [$entity]);
    $this->moduleHandler->alter('entity_operation', $operations, $entity);
    uasort($operations, '\Drupal\Component\Utility\SortArray::sortByWeightElement');

    // Add the space entity query to all operations.
    foreach ($operations as $key => $operation) {
      /** @var \Drupal\Core\Url $url */
      $url = $operation['url'];
      $url = $this->ensureDestination($url, $nodehive_space);
      $operations[$key]['url'] = $url;
    }

    return $operations;
  }

  /**
   * Gets this list's default operations.
   *
   * @param \Drupal\Core\Entity\EntityInterface $entity
   *   The entity.
   * @param \Drupal\nodehive_core\SpaceInterface|null $nodehive_space
   *   The space entity.
   *
   * @return array
   *   The array structure is identical to the return value of
   *   self::getOperations().
   */
  protected function getDefaultOperations(
    EntityInterface $entity,
    ?SpaceInterface $nodehive_space = NULL,
  ) {
    $operations = [];
    if ($entity->access('update') && $entity->hasLinkTemplate('edit-form')) {
      $operations['edit'] = [
        'title' => $this->t('Edit'),
        'weight' => 10,
        'url' => $this->ensureDestination(
          Url::fromRoute(
            "entity." . $entity->getEntityTypeId() . ".edit_form",
            [
              $entity->getEntityTypeId() => $entity->id(),
            ]
          ),
          $nodehive_space
        ),
      ];
    }

    if ($entity->access('delete') && $entity->hasLinkTemplate('delete-form')) {
      $operations['delete'] = [
        'title' => $this->t('Delete'),
        'weight' => 100,
        'attributes' => [
          'class' => ['use-ajax'],
          'data-dialog-type' => 'modal',
          'data-dialog-options' => Json::encode([
            'width' => 880,
          ]),
        ],
        'url' => $this->ensureDestination(
          Url::fromRoute(
            "entity." . $entity->getEntityTypeId() . ".delete_form",
            [
              $entity->getEntityTypeId() => $entity->id(),
            ]
          ),
          $nodehive_space
        ),
      ];
    }

    return $operations;
  }

  /**
   * Ensures that a destination is present on the given URL.
   *
   * @param \Drupal\Core\Url $url
   *   The URL object to which the destination should be added.
   * @param \Drupal\nodehive_core\SpaceInterface $nodehive_space
   *   The space entity.
   *
   * @return \Drupal\Core\Url
   *   The updated URL object.
   */
  protected function ensureDestination(Url $url, ?SpaceInterface $nodehive_space = NULL) {
    $query = $this->getRedirectDestination()->getAsArray();

    if ($nodehive_space) {
      $query['nodehive_space'] = $nodehive_space->id();
    }

    return $url->mergeOptions(
      [
        'query' => $query,
      ]
    );
  }

}
