<?php

namespace Drupal\pagedesigner_link\Plugin\pagedesigner\Handler;

use Drupal\Core\Language\LanguageInterface;
use Drupal\Core\Url;
use Drupal\linkit\SubstitutionManagerInterface;
use Drupal\pagedesigner\Entity\Element;
use Drupal\pagedesigner\Plugin\PlainFieldHandlerBase;
use Drupal\path_alias\AliasManagerInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;

/**
 * Process entities of type "link".
 *
 * @PagedesignerHandler(
 *   id = "link",
 *   name = @Translation("Link handler"),
 *   types = {
 *      "link",
 *      "href",
 *   },
 * )
 */
class Link extends PlainFieldHandlerBase {

  /**
   * The linkit substitution.
   *
   * @var \Drupal\linkit\SubstitutionManagerInterface
   */
  protected $linkitSubstitution;

  /**
   * The path alias manager.
   *
   * @var \Drupal\path_alias\AliasManagerInterface
   */
  protected $pathAliasManager;

  /**
   * {@inheritdoc}
   */
  public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
    $instance = parent::create($container, $configuration, $plugin_id, $plugin_definition);
    $instance->setLinkDependencies(
      $container->get('plugin.manager.linkit.substitution'),
      $container->get('path_alias.manager')
    );
    return $instance;
  }

  /**
   * Set link handler dependencies.
   *
   * @param \Drupal\linkit\SubstitutionManagerInterface $linkit_substitution
   *   The linkit substitution manager.
   * @param \Drupal\path_alias\AliasManagerInterface $path_alias_manager
   *   The path alias manager.
   */
  public function setLinkDependencies(SubstitutionManagerInterface $linkit_substitution, AliasManagerInterface $path_alias_manager) {
    $this->linkitSubstitution = $linkit_substitution;
    $this->pathAliasManager = $path_alias_manager;
  }

  /**
   * {@inheritdoc}
   */
  public function collectAttachments(array &$attachments) {
    $attachments['library'][] = 'pagedesigner_link/pagedesigner';
  }

  /**
   * {@inheritdoc}
   */
  public function serialize(Element $entity, array &$result = []) {
    $result = [
      'uri' => $entity->field_link->uri,
      'title' => $entity->field_link->title,
    ] + $result;
  }

  /**
   * {@inheritdoc}
   */
  public function get(Element $entity, string &$result = '') {
    $result = (string) $entity->field_link->uri;
    if (str_starts_with($result, '/')) {
      $url = Url::fromUri("internal:" . $result);
      if ($url->isRouted()) {
        $params = $url->getRouteParameters();
        $entity_type = key($params);
        if ($entity_type == 'media') {
          $mediaEntity = $this->entityTypeManager->getStorage($entity_type)->load($params[$entity_type]);
          if ($mediaEntity != NULL) {
            /** @var \Drupal\Core\Url $url */
            $url = $this->linkitSubstitution
              ->createInstance('media')
              ->getUrl($mediaEntity);
            if ($url) {
              $result = $url->toString();
            }
          }
        }
        elseif ($entity_type == 'node' && isset($params['node'])) {
          $nodeInternalPath = '/node/' . $params['node'];
          $langcode = trim(str_replace($nodeInternalPath, '', $result), '/');
          if (empty($langcode)) {
            $langcode = $this->languageManager
              ->getCurrentLanguage(LanguageInterface::TYPE_CONTENT)
              ->getId();
          }
          $result = $this->pathAliasManager->getAliasByPath($nodeInternalPath, $langcode);
          $result = '/' . $langcode . $result;
        }
      }
    }
  }

  /**
   * {@inheritdoc}
   */
  public function getContent(Element $entity, array &$list = [], $published = TRUE) {

  }

  /**
   * {@inheritdoc}
   */
  public function build(Element $entity, string $view_mode, array &$build = []) {
    $build = [];
    parent::build($entity, $view_mode, $build);
    $uri = (string) $entity->field_link->uri;
    if (str_starts_with($uri, '/')) {
      $url = Url::fromUri("internal:" . $uri);
      if ($url->isRouted()) {
        $params = $url->getRouteParameters();
        $entity_type = key($params);
        if ($entity_type == 'media') {
          $mediaEntity = $this->entityTypeManager->getStorage($entity_type)->load($params[$entity_type]);
          if ($mediaEntity != NULL) {
            $this->renderer->addCacheableDependency($build, $mediaEntity);
          }
        }
      }
    }
  }

  /**
   * {@inheritdoc}
   */
  public function patch(Element $entity, array $data) {
    // Treat empty urls as null.
    $uri = empty($data['uri']) ? NULL : $data['uri'];
    $entity->field_link->uri = $uri;
    $entity->field_link->title = empty($data['title']) ? '' : $data['title'];
    $entity->saveEdit();
  }

  /**
   * {@inheritdoc}
   */
  public function generate($definition, array $data, ?Element &$entity = NULL) {
    parent::generate(['type' => 'link', 'name' => 'link'], $data, $entity);
  }

}
