<?php

namespace Drupal\pagedesigner\Plugin\rest\resource;

use Drupal\Component\Serialization\Json;
use Drupal\Core\Language\LanguageInterface;
use Drupal\Core\Session\AccountProxyInterface;
use Drupal\pagedesigner\Entity\Element;
use Drupal\pagedesigner\Service\Renderer;
use Drupal\pagedesigner\Service\StateChanger;
use Drupal\rest\ModifiedResourceResponse;
use Drupal\rest\Plugin\ResourceBase;
use Psr\Log\LoggerInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;
use Symfony\Component\HttpKernel\Exception\BadRequestHttpException;
use Symfony\Component\HttpKernel\Exception\UnprocessableEntityHttpException;

/**
 * Provides a resource to get view modes by entity and bundle.
 *
 * @RestResource(
 *   id = "pagedesigner_clone",
 *   label = @Translation("Pagedesigner clone"),
 *   uri_paths = {
 *     "create" = "/pagedesigner/clone",
 *   }
 * )
 */
class CloneResource extends ResourceBase {

  /**
   * Constructs a new ElementResource object.
   *
   * @param array $configuration
   *   A configuration array containing information about the plugin instance.
   * @param string $plugin_id
   *   The plugin_id for the plugin instance.
   * @param mixed $plugin_definition
   *   The plugin implementation definition.
   * @param array $serializer_formats
   *   The available serialization formats.
   * @param \Psr\Log\LoggerInterface $logger
   *   A logger instance.
   * @param \Drupal\Core\Session\AccountProxyInterface $currentUser
   *   A current user instance.
   * @param \Drupal\pagedesigner\Service\StateChanger $stateChanger
   *   The state changer.
   * @param \Drupal\pagedesigner\Service\Renderer $renderer
   *   The pagedesigner renderer.
   */
  public function __construct(
    array $configuration,
    $plugin_id,
    $plugin_definition,
    array $serializer_formats,
    LoggerInterface $logger,
    protected AccountProxyInterface $currentUser,
    protected StateChanger $stateChanger,
    protected Renderer $renderer,
  ) {
    parent::__construct($configuration, $plugin_id, $plugin_definition, $serializer_formats, $logger);
  }

  /**
   * {@inheritdoc}
   */
  public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
    return new static(
          $configuration,
          $plugin_id,
          $plugin_definition,
          $container->getParameter('serializer.formats'),
          $container->get('logger.factory')->get('pagedesigner'),
          $container->get('current_user'),
          $container->get('pagedesigner.service.statechanger'),
          $container->get('pagedesigner.service.renderer')
      );
  }

  /**
   * Clone an element.
   *
   * @param \Symfony\Component\HttpFoundation\Request $request
   *   The request.
   *
   * @return \Drupal\rest\ModifiedResourceResponse
   *   The markup and styles of the clone.
   */
  public function post(Request $request) {

    $requestContent = Json::decode($request->getContent());
    if (empty($requestContent['original'])) {
      throw new BadRequestHttpException('The original key is mandatory for the post requests.');
    }
    if (!$this->currentUser->hasPermission('edit pagedesigner element entities')) {
      throw new AccessDeniedHttpException('You are not allowed to create pagedesigner content');
    }

    $original = $requestContent['original'];
    $language = \Drupal::languageManager()->getCurrentLanguage(LanguageInterface::TYPE_CONTENT)->getId();

    $entity = Element::load($original);
    if ($entity == NULL) {
      throw new BadRequestHttpException('Could not find original entity.');
    }
    if ($entity->hasTranslation($language)) {
      $entity = $entity->getTranslation($language);
    }

    $container = $entity->container->entity;
    if (!empty($requestContent['container']) && \is_numeric($requestContent['container'])) {
      $container = Element::load($requestContent['container']);
      if (!$container->hasTranslation($language)) {
        throw new UnprocessableEntityHttpException('The container does not exist in the given language.');
      }
    }
    $container = $container->getTranslation($language);
    $parent = NULL;
    if (!empty($requestContent['parent']) && \is_numeric($requestContent['parent'])) {
      if ($requestContent['parent'] == $requestContent['container']) {
        $parent = $container;
      }
      else {
        $parent = Element::load($requestContent['parent']);
        if (!$parent->hasTranslation($language)) {
          throw new UnprocessableEntityHttpException('The container does not exist in the given language.');
        }
        $parent = $parent->getTranslation($language);
      }
    }
    $clone = $this->stateChanger->copy($entity, $container, $parent)->getOutput();

    $renderer = $this->renderer->renderForEdit($clone, $clone->entity->entity);
    $response = new ModifiedResourceResponse([
      ['command' => 'pd_markup', 'data' => $renderer->getMarkup()],
      ['command' => 'pd_styles', 'data' => $renderer->getStyles()],
    ], 201);
    return $response;
  }

}
