<?php

namespace Comitium5\DesignerBundle\Controller\ContentSearch;

use Comitium5\DesignerBundle\Controller\BaseController;
use Comitium5\DesignerBundle\Entity\User;
use Comitium5\DesignerBundle\Factory\Search\Filter\LocaleMustFilter;
use Comitium5\DesignerBundle\ValueObjects\SearchOrderObject;
use Comitium5\DesignerBundle\ValueObjects\SearchQueryObject;
use Comitium5\DesignerBundle\ValueObjects\SearchResultObject;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request;

/**
 * Class ContentSearchController
 *
 * @author Oscar Jimenez <oscarjg19.developer@gmail.com>
 * @package ComitiumSuite\Bundle\AdminBundle\Controller\ContentSearch
 */
class ContentSearchController extends BaseController
{
    /**
     * Return json for autocomplete to global input search.
     *
     * @param Request $request
     *
     * @return JsonResponse
     */
    public function globalSuggestAction(Request $request)
    {
        $term = $request->query->get('q', '');

        $options = $this->buildSearchOptions($request);

        $searchProvider = $this->get('cs.search.provider');

        $results = $searchProvider->search($term, $options);

        return new JsonResponse($this->parseSearchResults($results));
    }

    /**
     * @param Request $request
     *
     * @return \Symfony\Component\HttpFoundation\RedirectResponse|void
     */
    public function urlRedirectionAction(Request $request)
    {
        $nameSpace = $request->query->get('namespace');
        $id = $request->query->get('id');

        if (!$nameSpace || !$id) {
            return;
        }

        $manager = $this->get('cs.manager.'.Utils::getEntityName($nameSpace));

        $entity = $manager->find($id);

        return $this->redirectToRoute($entity->getRoute(), $entity->getRouteParams());
    }

    /**
     * Return json for autocomplete on related content tab
     *
     * @param Request $request
     *
     * @return JsonResponse
     */
    public function relatedContentSuggestAction(Request $request)
    {
        $excludedContentTypes = $this->excludedContentTypesForRelatedContent();

        $options = $this->buildSearchOptions($request, $excludedContentTypes);

        $searchProvider = $this->get('cs.search.provider');

        $term = $request->query->get('q', '');

        $options["allSubSites"] = $this->allowSearchByMultipleSubSites();

        $results = $searchProvider->search($term, $options);

        return new JsonResponse($this->parseSearchResults($results));
    }

    /**
     * Render results displayed on related content tab
     *
     * @param Request $request
     *
     * @return \Symfony\Component\HttpFoundation\Response
     */
    public function relatedContentTabResultsAction(Request $request)
    {
        $excludedContentTypes = $this->excludedContentTypesForRelatedContent();

        $term = $request->query->get('q', '');
        $type = $request->query->get('type', null);
        $locale = $request->query->get('locale', null);

        $options = $this->buildSearchOptions($request, $excludedContentTypes);

        $searchProvider = $this->get('cs.search.provider');

        $options["allSubSites"] = $this->allowSearchByMultipleSubSites();

        $results = $searchProvider->search($term, $options);

        $tabOptions = [
            'groupBy' => 'selfContentType',
            'locale'  => $locale,
        ];

        $tabs = $searchProvider->search($term, $tabOptions);

        $pagination = $this
            ->get('knp_paginator')
            ->paginate(
                $results,
                $options['page'],
                $options['limit']
            );
        $pagination->setTotalItemCount((int) $results['total']);
        $pagination->setItems($this->parseSearchResults($results));

        return $this->render('AdminBundle:ContentSearch:content-search-results.html.twig', [
            'pagination' => $pagination,
            'type' => $type,
            'tabs' => $this->parseTabs($tabs, $type, $excludedContentTypes),
        ]);
    }

    /**
     * Return json for autocomplete on links modal
     *
     * @param Request $request
     *
     * @return JsonResponse
     */
    public function suggestLinkAction(Request $request)
    {
        $excludedContentTypes = [];

        $options = $this->buildSearchOptions($request, $excludedContentTypes);

        $term = $request->query->get('q', '');

        $this->addExistUrlOption($request, $options);

        $results = $this
            ->get("designer.repository.elastic_search")
            ->search(
                new SearchQueryObject(
                    $term,
                    "",
                    $options['page'],
                    $options['limit'],
                    [$this->get('designer.provider.subsite')->getSubsite()]
                )
            );

        return new JsonResponse($this->parseSearchResults($results->getResults()));
    }

    /**
     * Render results displayed on link results content
     *
     * @param Request $request
     *
     * @return \Symfony\Component\HttpFoundation\Response
     */
    public function renderLinkResultsAction(Request $request)
    {
        /**
         * @var User $user
         */
        $excludedContentTypes = [];

        $term = $request->query->get('q', '');
        $type = $request->query->get('type', null);
        $locale = $request->query->get('locale', null);
        $user = $this->getUser();

        $options = $this->buildSearchOptions($request, $excludedContentTypes);

        $this->addExistUrlOption($request, $options);

        $results = $this
            ->get('designer.repository.elastic_search')
            ->search(
                new SearchQueryObject(
                    $term,
                    "",
                    $options['page'],
                    $options['limit'],
                    $user->getSubsites(),
                    [
                        new LocaleMustFilter($locale)
                    ],
                    null,
                    $options['sort']
                )
            );

        $tabOptions = [
            'groupBy' => 'selfContentType',
            'locale'  => $locale,
        ];

        $this->addExistUrlOption($request, $tabOptions);

        $tabs = $this
            ->get('designer.repository.elastic_search')
            ->search(
                new SearchQueryObject(
                    $term,
                    "",
                    $options['page'],
                    $options['limit'],
                    $user->getSubsites(),
                    [
                        new LocaleMustFilter($locale)
                    ],
                    'selfContentType'
                )
            );

        $items = $this->parseSearchResults($results->getResults());

        $pagination = $this
            ->get('knp_paginator')
            ->paginate(
                $items,
                $results->getPage(),
                $results->getLimit()
            );

        $pagination->setTotalItemCount($results->getTotal());
        $pagination->setItems($items);

        return $this->render('Comitium5DesignerBundle:Links:search-results.html.twig', [
            'pagination' => $pagination,
            'type' => $type,
            'tabs' => $this->parseTabs($tabs, $type, $excludedContentTypes),
        ]);
    }

    /**
     * @param $results
     * @param $type
     * @param array $excludedContentTypes
     *
     * @return array
     */
    private function parseTabs(SearchResultObject $results, $type, $excludedContentTypes = [])
    {
        $tabs   = [
            'totals'  => 0,
            'results' => [],
        ];

        if ($results->getGroupByCollection() === null) {
            return $tabs;
        }

        foreach ($results->getGroupByCollection()->getObjects() as $resultObject) {
            $resultType = $resultObject->getValue();

            if (in_array($resultType, $excludedContentTypes)) {
                continue;
            }

            $tabs['results'][] = [
                'type'     => $resultType,
                'text'     => "",//$contentTypesGlobal[$resultType]['text'],
                'count'    => $resultObject->getQuantity(),
                'selected' => $resultType == $type,
            ];

            $tabs['totals'] += $resultObject->getQuantity();
        }

        return $tabs;
    }

    /**
     * @return bool
     * @throws \Exception
     */
    private function allowSearchByMultipleSubSites()
    {
        $data = $this
            ->get("cs.manager.config_parameter")
            ->getParamValues(
                ConfigParameterKey::GENERAL,
                "search_multiple_subsites"
            );

        return boolval($data);
    }

    /**
     * @param Request $request
     * @param array $options
     *
     * @return array
     */
    private function addExistUrlOption(Request $request, array &$options)
    {
        $existUrl = $request->query->get('existUrl', true);

        if ($existUrl === true) {
            $options = array_merge($options, [
                "exist" => [
                    "url" => $existUrl,
                ]
            ]);
        }

        return $options;
    }
}
