<?php

namespace Drupal\castorcito;

use Drupal\castorcito\Entity\CastorcitoCategory;
use Drupal\Core\Config\Entity\ConfigEntityListBuilder;
use Drupal\Core\Entity\EntityInterface;
use Drupal\Component\Serialization\Json;
use Drupal\Core\Url;

/**
 * Provides a listing of Castorcito components.
 */
class CastorcitoComponentListBuilder extends ConfigEntityListBuilder {

  /**
   * The number of entities to list per page, or FALSE to list all entities.
   *
   * For example, set this to FALSE if the list uses client-side filters that
   * require all entities to be listed (like the views overview).
   *
   * @var int|false
   */
  protected $limit = false;

  /**
   * {@inheritdoc}
   */
  public function render() {
    $entities = $this->load();
    $categories = [];

    // Organize components by category
    foreach ($entities as $entity) {
      $category = $entity->get('category') ?? 'Uncategorized';
      $categories[$category][] = $entity;
    }

    $build = [
      '#type' => 'container',
      '#attributes' => ['class' => ['castorcito-component-list']],
    ];

    $castorcito_manager = \Drupal::service('castorcito.manager');
    foreach ($categories as $category_name => $entities) {
      $category = CastorcitoCategory::load($category_name);
      $category_label = $category && $category->label() ? $category->label() : $this->t('Unknown Category');
      $header = [
        'only_container' => $this->t('In container'),
        'label' => $this->t('Label'),
        'id' => $this->t('Machine name'),
        'description' => $this->t('Description'),
        'inuse' => $this->t('In use'),
        'operations' => $this->t('Operations'),
      ];

      $rows = [];
      foreach ($entities as $entity) {
        $operations = $this->buildOperations($entity);
        if ($castorcito_manager->componentUsage($entity->id())) {
          unset($operations['#links']['delete']);
        }

        $rows[] = [
          'data' => [
            'only_container' => !empty($entity->get('inside_container')) ? '✔' : '',
            'label' => $entity->label(),
            'id' => $entity->id(),
            'description' => $entity->get('description'),
            'inuse' => $this->getInUseMarkup($entity->id()),
            'operations' => ['data' => $operations],
          ],
        ];
      }

      $build['category_' . $category_name] = [
        '#type' => 'details',
        '#title' => "{$category_label} (" . count($entities) . ")",
        '#open' => FALSE,
        'table' => [
          '#type' => 'table',
          '#header' => $header,
          '#rows' => $rows,
          '#empty' => $this->t('No components in this category.'),
        ],
      ];
    }

    return $build;
  }

  /**
   * {@inheritdoc}
   */
  public function getDefaultOperations(EntityInterface $entity) {
    $clone = [
      'title' => $this->t('Clone'),
      'weight' => 200,
      'url' => $entity->toUrl('clone-form'),
    ];

    $operations = parent::getDefaultOperations($entity) + [
      'clone' => $clone,
    ];

    // Remove destination URL from the edit link to allow editing component
    // Component.
    if (isset($operations['edit'])) {
      $operations['edit']['url'] = $entity->toUrl('edit-form');
    }

    return $operations;
  }

  /**
   * Get the markup for in use.
   */
  private function getInUseMarkup(string $component_id) {
    $castorcito_manager = \Drupal::service('castorcito.manager');
    if ($castorcito_manager->componentUsage($component_id)) {
      $markup = [
        '#type' => 'link',
        '#title' => t('In use'),
        '#url' => Url::fromRoute('entity.castorcito_component.inuse_modal', ['castorcito_component' => $component_id]),
        '#options' => [
          'attributes' => [
            'class' => ['use-ajax'],
            'data-dialog-type' => 'modal',
            'data-dialog-options' => Json::encode([
              'width' => 700,
            ]),
          ],
        ],
        '#attached' => ['library' => ['core/drupal.dialog.ajax']],
      ];
    }
    else {
      $markup = [
        '#markup' => t('Not in use'),
      ];
    }

    return \Drupal::service('renderer')->render($markup);
  }

}
