<?php

namespace Drupal\nodehive_area_fragment\Form;

use Drupal\Core\Ajax\AjaxResponse;
use Drupal\Core\Ajax\RedirectCommand;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Url;

/**
 * Provides a form for removing a fragment from a area.
 */
class FragmentListBuilderForm extends SpaceListBuilderFormBase {

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

  /**
   * {@inheritdoc}
   */
  public function buildForm(array $form, FormStateInterface $form_state) {
    $build = parent::buildForm($form, $form_state);
    $nodehive_space_id = $this->getRouteMatch()->getParameter('nodehive_space');
    $nodehive_space = NULL;
    if ($nodehive_space_id) {
      $nodehive_space = $this->entityTypeManager
        ->getStorage('nodehive_space')
        ->load($nodehive_space_id);
    }

    $request_query = $this->getRequest()->query->all();
    $build['add_fragment'] = [
      '#type' => 'container',
    ];

    $header = $this->listBuilderHelper->buildFragmentHeader();
    $header['operations'] = $this->t("Operations");
    $build['search_wrapper'] = [
      '#type' => 'fieldset',
      '#attributes' => [
        'class' => [
          'search-form',
        ],
      ],
    ];

    $build['search_wrapper']['search'] = [
      '#type' => 'textfield',
      '#title' => $this->t('Title'),
      '#default_value' => $request_query['search'] ?? NULL,
    ];

    $types_options = [];
    $types = $this->entityTypeManager
      ->getStorage("nodehive_fragment_type")
      ->loadMultiple();

    $types_options[""] = $this->t("All");
    foreach ($types as $id => $type) {
      $types_options[$id] = $type->label();
    }
    $build['search_wrapper']['fragment_type'] = [
      '#type' => 'select',
      '#options' => $types_options,
      '#title' => $this->t('Fragment Type'),
      '#default_value' => $request_query['fragment_type'] ?? NULL,
    ];

    $areas_options = [];

    if ($nodehive_space_id) {
      $areas = $this->entityTypeManager
        ->getStorage("nodehive_area")
        ->loadByProperties([
          'space_id' => $nodehive_space_id,
        ]);
    }
    else {
      $areas = $this->entityTypeManager
        ->getStorage("nodehive_area")
        ->loadMultiple();
    }

    $areas_options[""] = $this->t("All");
    foreach ($areas as $id => $area) {
      $areas_options[$id] = $area->label();
    }

    $build['search_wrapper']['area'] = [
      '#type' => 'select',
      '#options' => $areas_options,
      '#title' => $this->t('Area'),
      '#default_value' => $request_query['area'] ?? NULL,
    ];

    if (!$nodehive_space_id) {
      $space_options = [];
      $spaces = $this->entityTypeManager
        ->getStorage("nodehive_space")
        ->loadMultiple();

      $space_options[""] = $this->t("All");
      foreach ($spaces as $id => $space) {
        $space_options[$id] = $space->label();
      }

      $build['search_wrapper']['space'] = [
        '#type' => 'select',
        '#options' => $space_options,
        '#title' => $this->t('Space'),
        '#default_value' => $request_query['space'] ?? NULL,
      ];
    }
    else {
      $request_query['space'] = $nodehive_space_id;
    }

    $build['search_wrapper']['submit'] = [
      '#type' => 'submit',
      '#value' => $this->t('Search'),
      '#ajax' => [
        'callback' => [$this, 'ajaxRedirect'],
      ],
    ];

    $build['fragments'] = [
      '#type' => 'table',
      '#header' => $header,
    ];

    $search_query = [
      'search' => $request_query['search'] ?? "",
    ];

    if (isset($request_query['space']) && $request_query['space']) {
      $search_query['space_id'] = $request_query['space'];
    }

    if (isset($request_query['fragment_type']) && $request_query['fragment_type']) {
      $search_query['type'] = $request_query['fragment_type'];
    }

    $entity_ids = $this->listBuilderHelper->getFragmentEntityIds($search_query);

    if (isset($request_query['area']) && $request_query['area']) {
      $area = $this->entityTypeManager->getStorage('nodehive_area')->load($request_query['area']);
      $area_fragments_reference = $area->fragment_id->referencedEntities();
      $area_fragments_ids = [];
      foreach ($area_fragments_reference as $fragment) {
        $area_fragments_ids[] = $fragment->id();
      }

      foreach ($entity_ids as $key => $fragment) {
        if (!in_array($fragment->id(), $area_fragments_ids)) {
          unset($entity_ids[$key]);
        }
      }
    }

    foreach ($entity_ids as $fragment) {
      if ($row = $this->listBuilderHelper->buildFragmentRow($fragment)) {
        // Add destination to label url.
        /** @var \Drupal\Core\Url $url */
        $url = $row['label']['data']['#url'];
        $url = $this->ensureDestination($url, $nodehive_space);

        $row['label']['data']['#url'] = $url;

        $row[] = [
          'data' => $this->buildOperations($fragment, $nodehive_space),
        ];
        $build['fragments']['#rows'][$fragment->id()] = $row;
      }
    }

    $build['#attached']['library'][] = 'nodehive_area_fragment/nodehive_fragment.space_list_builder';

    return $build;
  }

  /**
   * {@inheritdoc}
   */
  public function ajaxRedirect(array &$form, FormStateInterface $form_state) {
    $query = $this->getRequest()->query->all();
    $nodehive_space_id = $form_state->getValue('nodehive_space_id');

    // Remove ajax stuff.
    unset($query['ajax_form']);
    unset($query['_wrapper_format']);

    // Add title.
    $query['search'] = $form_state->getValue('search');
    $query['fragment_type'] = $form_state->getValue('fragment_type');
    $query['area'] = $form_state->getValue('area');
    $query['space'] = $form_state->getValue('space');
    if (empty($query['space'])) {
      $query['space'] = $nodehive_space_id;
    }

    // Build a new redirect.
    if ($nodehive_space_id) {
      $url = Url::fromRoute(
        'entity.fragment.space_collection',
        [
          'nodehive_space' => $nodehive_space_id,
        ],
        [
          'query' => $query,
        ],
      );
    }
    else {
      $url = Url::fromRoute(
        'entity.nodehive_fragment.collection',
        [],
        [
          'query' => $query,
        ],
      );
    }

    $command = new RedirectCommand($url->toString());
    $response = new AjaxResponse();
    return $response->addCommand($command);
  }

  /**
   * {@inheritdoc}
   */
  public function submitForm(array &$form, FormStateInterface $form_state) {
    $nodehive_space_id = $this->getRouteMatch()->getParameter('nodehive_space');
    $form_state->setValue('nodehive_space_id', $nodehive_space_id);

    if ($nodehive_space_id) {
      return $this->redirect(
        'entity.fragment.space_collection',
        [
          'nodehive_space' => $nodehive_space_id,
        ],
      );
    }

    return $this->redirect(
      'entity.nodehive_fragment.collection',
    );
  }

}
