<?php

namespace Drupal\pagedesigner_layout\Plugin\rest\resource;

use Drupal\Component\Serialization\Json;
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\BadRequestHttpException;

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

  /**
   * A current user instance.
   *
   * @var \Drupal\Core\Session\AccountProxyInterface
   */
  protected $currentUser;

  /**
   * The handler manager.
   *
   * @var \Drupal\pagedesigner\Service\StateChanger
   */
  protected $stateChanger;

  /**
   * The handler manager.
   *
   * @var \Drupal\pagedesigner\Service\Renderer
   */
  protected $renderer;

  /**
   * 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 $current_user
   *   A current user instance.
   * @param \Drupal\pagedesigner\Service\StateChanger $state_changer
   *   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,
    AccountProxyInterface $current_user,
    StateChanger $state_changer,
    Renderer $renderer,
  ) {
    parent::__construct($configuration, $plugin_id, $plugin_definition, $serializer_formats, $logger);

    $this->currentUser = $current_user;
    $this->stateChanger = $state_changer;
    $this->renderer = $renderer;
  }

  /**
   * {@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')
      );
  }

  /**
   * Responds to GET requests.
   *
   * Returns the layout.
   *
   * @param int $id
   *   ID of the entity.
   *
   * @return \Drupal\rest\ModifiedResourceResponse
   *   The HTTP response object.
   *
   * @throws \Symfony\Component\HttpKernel\Exception\HttpException
   *   Throws exception expected.
   */
  public function get($id) {
    $layout = Element::load($id);
    $entity = $layout->children->entity;
    $clone = $this->stateChanger->copy($entity)->getOutput();
    $renderer = $this->renderer->renderForEdit($clone);
    $response = new ModifiedResourceResponse([
      ['command' => 'pd_markup', 'data' => $renderer->getMarkup()],
      ['command' => 'pd_styles', 'data' => $renderer->getStyles()],
    ], 201);
    return $response;
  }

  /**
   * Responds to POST requests.
   *
   * Creates a new layout based of the given element id.
   *
   * @param \Symfony\Component\HttpFoundation\Request $request
   *   The request.
   *
   * @return \Drupal\rest\ModifiedResourceResponse
   *   The HTTP response object.
   *
   * @throws \Symfony\Component\HttpKernel\Exception\HttpException
   *   Throws exception expected.
   *
   * @throws \Symfony\Component\HttpKernel\Exception\BadRequestHttpException
   *   If the request is malformed.
   */
  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.');
    }

    $original = $requestContent['original'];
    $entity = Element::load($original);
    $clone = $this->stateChanger->copy($entity)->getOutput();
    $layout = Element::create([
      'type' => 'layout',
      'name' => $requestContent['name'],
    ]);
    $layout->field_content->value = $requestContent['description'];
    $layout->children->target_id = $clone->id();
    $layout->save();
    $clone->parent->target_id = $layout->id();
    $clone->save();
    return new ModifiedResourceResponse([$layout], 200);
  }

  /**
   * Responds to DELETE requests.
   *
   * Deletes the layout with the given id.
   *
   * @param int $id
   *   ID of the entity.
   *
   * @return \Drupal\rest\ModifiedResourceResponse
   *   The HTTP response object.
   *
   * @throws \Symfony\Component\HttpKernel\Exception\HttpException
   *   Throws exception expected.
   *
   * @throws \Symfony\Component\HttpKernel\Exception\BadRequestHttpException
   *   If the request is malformed.
   */
  public function delete($id) {
    $layout = Element::load($id);
    \Drupal::service('pagedesigner.service.element_handler')->delete($layout);
    return new ModifiedResourceResponse(NULL, 204);
  }

}
