<?php

namespace Comitium5\DesignerBundle\Controller;

use Comitium5\DesignerBundle\Helper\IcoUtils;
use Comitium5\DesignerBundle\Helper\Utils;
use Comitium5\DesignerBundle\Model\Interfaces\Subsite\SubsiteInterface;
use Comitium5\DesignerBundle\Provider\Locale\LocaleProvider;
use Comitium5\DesignerBundle\ValueObjects\SearchEntityObject;
use Comitium5\DesignerBundle\ValueObjects\SearchOrderObject;
use Doctrine\ORM\EntityNotFoundException;
use Doctrine\ORM\QueryBuilder;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\Form\Form;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;
use Symfony\Component\HttpKernel\Exception\BadRequestHttpException;
use Symfony\Component\HttpKernel\HttpKernelInterface;

/**
 * Class BaseController
 * @author Fernando Pradas <fernando@bab-soft.com>
 */
class BaseController extends Controller
{
    const SORT_DATE = "date";
    const SORT_RELEVANCE = "relevance";
    const DEFAULT_PAGE_LIMIT = 10;

    /**
     * @param Request $request
     * @return bool
     */
    public function checkRequest(Request $request)
    {
        if ($this->container->getParameter('kernel.environment') === 'test') {
            return true;
        }

        if (
            $request->isXmlHttpRequest() === false &&
            HttpKernelInterface::MASTER_REQUEST === $request->attributes->get('_type')
        ) {
            throw new BadRequestHttpException(Response::$statusTexts[Response::HTTP_BAD_REQUEST]);
        }
    }

    /**
     * @param Request $request
     */
    public function handleIfMasterRequest(Request $request)
    {
        if (HttpKernelInterface::MASTER_REQUEST === $request->attributes->get('_type')) {
            throw new BadRequestHttpException(Response::$statusTexts[Response::HTTP_BAD_REQUEST]);
        }
    }

    /**
     * @param Request $request
     *
     * @return bool
     */
    public function handleIfNotAjaxRequest(Request $request)
    {
        if ($this->container->getParameter('kernel.environment') === 'test') {
            return true;
        }
        if (!$request->isXmlHttpRequest()) {
            throw new BadRequestHttpException(Response::$statusTexts[Response::HTTP_BAD_REQUEST]);
        }
    }

    /**
     * @param $object
     * @param bool|true $throwException
     * @return bool
     */
    public function handleIfNotFound($object, $throwException = true)
    {
        if ($this->container->getParameter('kernel.environment') === 'test') {
            return true;
        }

        if (null === $object && $throwException === true) {
            throw $this->createNotFoundException();
        } elseif (null === $object && $throwException === false) {
            return false;
        }

        return true;
    }

    /**
     * @return SubsiteInterface|null
     * @throws \GuzzleHttp\Exception\GuzzleException
     */
    public function getSubsite()
    {
        return $this
            ->get("designer.provider.subsite")
            ->getSubSite();
    }

    /**
     * @return LocaleInterface
     * @throws EntityNotFoundException
     */
    public function getSubsiteDefaultLocale()
    {
        $session = $this
            ->get('request_stack')
            ->getCurrentRequest()
            ->getSession();

        $serialized = $session->get(LocaleProvider::SESSION_NAME);

        if (!empty($serialized)) {
            return unserialize($serialized);
        }

        throw new \RuntimeException("There's no defined locale");
    }

    /**
     * @return \Comitium5\DesignerBundle\Model\Interfaces\LocaleInterface|null
     * @throws \GuzzleHttp\Exception\GuzzleException
     */
    public function getReferencedSubsiteDefaultLocale()
    {
        return $this
            ->get("designer.provider.locale")
            ->getDefaultLocale();
    }

    /**
     * @param $type
     * @param $message
     * @param int $count
     */
    public function addToastrMessage($type, $message, $count = 1)
    {
        $type = 'toastr-'.$type;
        $message = $this->get('translator')->transChoice($message, $count, array("%count%" => $count));

        $this->addFlash($type, $message);
    }

    /**
     * @param Request $request
     * @param $builder
     * @param int $perPagew
     * @param array $options
     *
     * @return \Knp\Component\Pager\Pagination\PaginationInterface
     */
    public function paginate(Request $request, $builder, $perPage = self::DEFAULT_PAGE_LIMIT, $options = [])
    {
        if (!$this->container->has('knp_paginator')) {
            throw new \LogicException('The KnpPaginatorBundle is not registered in your application.');
        }

        $page = $request->attributes->get("page", $request->get("page", 1));

        /*
         * @var Knp\Component\Pager\Pagination\SlidingPagination $pagination
         */
        $pagination = $this
            ->get('knp_paginator')
            ->paginate(
                $builder,
                $page,
                $perPage,
                $options
            );

        $pagination->setUsedRoute($request->get('_route'));

        return $pagination;
    }

    /**
     * @return \Doctrine\ORM\EntityManager
     */
    public function getEntityManager()
    {
        return $this->get("doctrine.orm.default_entity_manager");
    }

    /**
     * Returns the FQDN of current CRUD working class
     * @return string
     */
    public function getWorkingClass()
    {
        return '';
    }

    /**
     * @return object
     */
    public function getRepository()
    {
        return $this
            ->getEntityManager()
            ->getRepository($this->getWorkingClass());
    }

    /**
     * @return \Doctrine\Common\Persistence\Mapping\ClassMetadata
     * @throws \Doctrine\Common\Persistence\Mapping\MappingException
     * @throws \ReflectionException
     */
    public function getMetadata()
    {
        return $this
            ->getEntityManager()
            ->getMetadataFactory()
            ->getMetadataFor($this->getWorkingClass());
    }

    /**
     * @param null $message
     * @param null $title
     *
     * @return JsonResponse
     */
    protected function responseAvoidDeletion($title = null, $message = null)
    {
        $message = $message === null ? $this->get('translator')->trans('common.messages.delete.avoid_message') : $message;
        $title   = $title   === null ? $this->get('translator')->trans('common.messages.delete.avoid_title') : $title;

        return new JsonResponse(array(
            'title'   => $title,
            'message' => $message,
        ), Response::HTTP_UNAUTHORIZED);
    }

    /**
     * @param $entity
     *
     * @return string
     */
    protected function generateTranslateLink($entity)
    {
        $masterRequest = $this->get('request_stack')->getMasterRequest();
        $entityLocale  = $masterRequest->get('entityLocale', null);
        $forIframe  = (int) $masterRequest->get("forIframe");

        $entityName = Utils::getEntityNameType($entity);
        $forceEntityName = $entityName;

        if ($entity instanceof PrivateContentInterface) {
            if ($entity->isPrivateContent()) {
                $forceEntityName = "privateContent";
            }
        }

        return $this->generateUrl('cs_core.translate', [
            'entityName' => $entityName,
            'id' => $entity->getId(),
            'orig' => $entityLocale !== null ? $entityLocale : $entity->getDefaultLang()->getLocale()->getCode(),
            'ignoreReferer' => 1,
            'forIframe' => $forIframe,
            "forceEntityName" => $forceEntityName,
        ]);
    }

    /**
     * @param AbstractEntity|array $entity
     */
    public function unBlockContent($entity)
    {
        $blockedContentManger = $this->get("cs.manager.block_content");

        if (is_object($entity)) {
            if ($entity instanceof AbstractEntity) {
                $blockedContentManger->unBlockContent($entity);
            }
        } elseif (is_array($entity)) {
            foreach ($entity as $item) {
                if ($item instanceof AbstractEntity) {
                    $blockedContentManger->unBlockContent($item);
                }
            }
        }
    }

    /**
     * Generic method to check granted
     * See VoterInterface to know attributes
     *
     * @param $attribute
     * @param $entity
     * @param $throwException
     * @param $redirectRoute
     */
    public function handleGrantedGenericAccess(
        $attribute,
        $entity,
        $redirectRoute = null,
        $throwException = true
    ) {
        // Check if the object exists first
        $this->handleIfNotFound($entity, $throwException);

        // Check if the entity has current subsite
        if ($entity instanceof SubsiteRelationInterface || $entity instanceof SubsiteCollectionInterface || $entity instanceof RolesSubsiteCollectionInterface) {
            $this->handleGrantedEntitySubSiteRelation($attribute, $entity, $redirectRoute, $throwException);
        }

        if ($entity instanceof PrivateContentInterface) {
            if ($entity->isPrivateContent()) {
                if ($entity->getUser() !== $this->getUser()) {
                    throw new AccessDeniedHttpException();
                }
            }
        }

        $this->handleGuestUserPermissions($entity);

        // Add more logic here ...
    }

    /**
     * See VoterInterface to know attributes
     *
     * @param string $attributes
     * @param object $entity
     * @param boolean $throwException
     * @param string $redirectRoute
     * @return bool
     * @throws \Exception
     */
    public function handleGrantedEntitySubSiteRelation(
        $attributes,
        $entity,
        $redirectRoute = null,
        $throwException = true
    ) {
        if (!$entity instanceof SubsiteRelationInterface &&
            !$entity instanceof SubsiteCollectionInterface &&
            !$entity instanceof RolesSubsiteCollectionInterface
        ) {
            throw new \Exception("Entity must implement SubsiteRelationInterface, SubsiteRelationInterface or RolesSubsiteCollectionInterface");
        }

        $message = $this
            ->get("translator")
            ->trans("cs_core.messages.granted.subsite_entity_denied");

        if (!$this->isGranted($attributes, $entity)) {
            if ($throwException === true) {
                if ($redirectRoute !== null) {
                    $this->addToastrMessage("warning", $message);
                    throw new ContentSubSiteAccessDeniedException($message, $redirectRoute);
                } else {
                    throw $this->createAccessDeniedException($message);
                }

            } else {
                return false;
            }
        }

        return true;
    }

    /**
     * @param Request $request
     * @param SearchableRepositoryInterface $repository
     * @return array
     * @throws \Exception
     */
    public function processSelected(Request $request, SearchableRepositoryInterface $repository)
    {
        $bulkManager = $this->get('cs.manager.bulk.list_actions');

        $searchListManager = $this
            ->get('cs.manager.search.search_list')
            ->setSearchableRepository($repository);

        return $bulkManager->processSelected($searchListManager, $request);
    }

    /**
     * @param Request $request
     * @param SearchableRepositoryInterface $repository
     * @param Form $form
     * @param array $params
     * @return array
     */
    public function processSelectedAdvancedSearch(
        Request $request,
        SearchableRepositoryInterface $repository,
        Form $form,
        $params = []
    ) {
        $bulkManager = $this->get('cs.manager.bulk.list_actions');

        $searchListManager = $this
            ->get('cs.manager.search.search_list')
            ->setSearchableRepository($repository);

        return $bulkManager->processSelectedAdvancedSearch($searchListManager, $form, $request, $params);
    }


    /**
     * @param ObjectManagerInterface $manager
     * @return \ComitiumSuite\Bundle\ApiRestBundle\Manager\ApiRestCacheManager|object
     * @throws \Doctrine\ORM\ORMException
     * @throws \Exception
     */
    private function getApiRestCache(ObjectManagerInterface $manager)
    {
        $cache = $this->get('api_rest.manager.cache');
        $cache->setObjectManager($manager);

        $provider = $this->get('cs.provider.locale');
        $cache->setLocale($provider->getDefaultLocale());

        $provider = $this->get('cs.provider.subsite');
        $cache->setSubsite($provider->getSubSite());

        return $cache;
    }

    /**
     * @param IdentifiableInterface $entity
     * @param ObjectManagerInterface $manager
     * @param bool $force
     * @throws \Doctrine\ORM\ORMException
     * @throws \Exception
     */
    protected function refreshCache(IdentifiableInterface $entity, ObjectManagerInterface $manager, $force = false)
    {
        AbstractSerializeEntity::setRoutingProvider($this->get("cs.provider.routing"));

        $cache = $this->getApiRestCache($manager);

        if ($force || $cache->existsEntity($entity)) {
            $save = true;
            if ($entity instanceof EnabledInterface) {
                $save = $entity->isEnabled();
            } elseif (
                $entity instanceof SelfContentTypeInterface
                && $entity instanceof StatefulInterface
                && !is_null($entity->getState())
            ) {
                $contentType = $entity::getSelfContentType();
                $em = $this->get('cs_core.orm.entity_manager');

                $states = $em
                    ->getRepository(
                        'ComitiumSuite\Components\Workflow\Entity\State'
                    )
                    ->findByContentTypeAndBehaviourResult(
                        $contentType, StateBehaviours::PUBLISHED
                    );
                $save = in_array($entity->getState(), $states);
            }

            if ($save) {
                $cache->updateEntity($entity);

                if ($entity instanceof SelfContentTypeInterface) {
                    $url = $this
                        ->get('cs.provider.routing')
                        ->generate($entity);

                    if ($url) {
                        $this
                            ->get('cs.cache.invalidator_collector')
                            ->refresh($url)
                            ->flush();
                        ;
                    }
                }
            } else {
                if ($entity instanceof SelfContentTypeInterface) {
                    $url = $this
                        ->get('cs.provider.routing')
                        ->generate($entity);

                    if ($url) {
                        $this
                            ->get('cs.cache.invalidator_collector')
                            ->purge($url)
                        ;
                    }
                }

                $cache->removeEntity($entity);
            }
        }
    }

    /**
     * @param IdentifiableInterface $entity
     * @param ObjectManagerInterface $manager
     * @throws \Doctrine\ORM\ORMException
     * @throws \Exception
     */
    protected function deleteCache(IdentifiableInterface $entity, ObjectManagerInterface $manager)
    {
        $this
            ->getApiRestCache($manager)
            ->removeEntity($entity);
    }

    /**
     * @param AbstractEntity $entity
     */
    protected function persistAssetContentRelation(AbstractEntity $entity)
    {
        $this
            ->get("cs.manager.asset_content_relation")
            ->normalizeAndPersistFromAny($entity);
    }

    /**
     * @param AbstractEntity $entity
     */
    protected function deleteAssetContentRelation(AbstractEntity $entity)
    {
        $this
            ->get("cs.manager.asset_content_relation")
            ->normalizeAndRemoveFromAny($entity);
    }

    /**
     * @param Form $form
     * @param null $defaultUrl
     * @return RedirectResponse|static
     * @throws \Doctrine\ORM\ORMException
     * @throws \Exception
     */
    protected function handleFormRedirect(
        Form $form,
        $defaultUrl = null
    ) {
        $masterRequest = $this
            ->get('request_stack')
            ->getMasterRequest();

        $url = $defaultUrl;

        $entity = $form->getData();

        if ($form->has('_uniqid') && $masterRequest->get('ignoreReferer') === null) {
            $uniqueFormManager = $this->get('cs.form.manager.uniqueform');
            $url = $uniqueFormManager->get($form, 'HTTP_REFERER', $defaultUrl);
            $uniqueFormManager->remove($form, 'HTTP_REFERER');
        }

        if ($masterRequest->get('goToTranslate')) {
            $url = $this->generateTranslateLink($entity);
        }

        if ($masterRequest->get('goToPreview')) {
            if ($entity instanceof ContentSearchItemInterface) {
                $url = $this->generateUrl($entity->getRoute(), $entity->getRouteParams());

                $previewUrl = $this
                    ->generateUrl('pages_content_preview', [
                        'class' => Utils::getClass($entity),
                        'entityId' => $entity->getId(),
                        'locale' => $this->get("cs.provider.locale")->getDefaultLocale()->getCode(),
                        'referer' => $url
                    ]);

                $url .= "?previewUrl=".urlencode($previewUrl)."&ignoreReferer=1";
            }
        }

//        $this->unBlockContent($entity);

        if ($masterRequest->attributes->has("autoSaveKey")) {
            $this->removeAutoSaveData($masterRequest->attributes->get("autoSaveKey"));
        }

        if ($masterRequest->get('dataType') !== "json") {
            return new RedirectResponse($url);
        }

        return JsonResponse::create(["url" => $url]);
    }

    /**
     * @param Request $request
     * @param int $id
     * @return Response
     */
    public function autoSaveAction(Request $request, $id = 0)
    {
        $key   = $request->get("key");
        $formId     = $request->get("formId");
        $refererUrl = $request->get("referer");

        if (!$key || !$formId || !$refererUrl) {
            return Response::create([], Response::HTTP_BAD_REQUEST);
        }

        $redisKey = $this->buildAutoSaveRedisKey($key);

        if ($redisKey !== null) {
            parse_str($request->get("formData"), $parsed);

            if (!empty($parsed[$formId])) {
                if (isset($parsed[$formId]["_token"])) {
                    unset($parsed[$formId]["_token"]);
                }

                $this
                    ->autoSaveDraftHandler()
                    ->save($redisKey, [
                        $formId   => $parsed[$formId],
                        "referer" => $refererUrl,
                    ]);
            }

            return JsonResponse::create();
        }

        return JsonResponse::create([], Response::HTTP_BAD_REQUEST);
    }

    /**
     * @param Request $request
     * @return Response
     */
    public function checkAutoSaveAction(Request $request)
    {
        $formId = $request->get("formId");
        $key    = $request->get("key");

        if (!$key || !$formId) {
            return Response::create([], Response::HTTP_BAD_REQUEST);
        }

        $redisKey = $this->buildAutoSaveRedisKey($key);

        if ($redisKey !== null) {
            $formData = $this
                ->autoSaveDraftHandler()
                ->get($redisKey);

            $allowed = false;

            if (empty($formData[$formId])) {
                $allowed = true;
            }

            return JsonResponse::create([
                "allowed" => $allowed,
                "referer" => isset($formData["referer"]) ? $formData["referer"] : null,
            ]);
        }

        return JsonResponse::create([], Response::HTTP_BAD_REQUEST);
    }

    /**
     * @param Request $request
     * @return Response
     */
    public function discardAutoSaveAction(Request $request)
    {
        $key = $request->get("key");

        if (!$key) {
            return Response::create([], Response::HTTP_BAD_REQUEST);
        }

        $success  = false;
        $redisKey = $this->buildAutoSaveRedisKey($key);

        if ($redisKey !== null) {
            $data = $this
                ->autoSaveDraftHandler()
                ->get($redisKey);

            $this
                ->autoSaveDraftHandler()
                ->delete($redisKey);

            $success = true;

            if (!$request->isXmlHttpRequest()) {
                return $this->redirect(!empty($data["referer"]) ? $data["referer"] : "/");
            }
        }

        return JsonResponse::create([
            "success" => $success
        ]);
    }

    /**
     * @param Request $request
     * @param $formId
     * @param $key
     */
    protected function rescueAutoSaveData(
        Request $request,
        $formId,
        $key
    ) {
        $request
            ->attributes
            ->set("autoSaveKey", $key);

        if ($request->query->get("draft")) {
            $redisKey = $this->buildAutoSaveRedisKey($key);

            if ($redisKey !== null) {
                $formData = $this
                    ->autoSaveDraftHandler()
                    ->get($redisKey);

                if (!empty($formData[$formId])) {
                    $request->query->set($formId, $formData[$formId]);
                }
            }
        }
    }

    /**
     * @param $key
     * @return bool
     */
    protected function removeAutoSaveData($key)
    {
        $redisKey = $this->buildAutoSaveRedisKey($key);

        if ($redisKey !== null) {
            return $this
                ->autoSaveDraftHandler()
                ->delete($redisKey);
        }

        return false;
    }

    /**
     * @param $key
     * @return null|string
     * @throws \Doctrine\ORM\ORMException
     * @throws \Exception
     */
    private function buildAutoSaveRedisKey($key)
    {
        $user  = $this->getUser();

        if ($user instanceof UserInterface) {
            $subSiteAcronym = $this
                ->get("cs.provider.subsite")
                ->getSubSite()
                ->getAcronym();

            return sprintf(
                "auto_save_subsite:%s_user:%s_key:%s",
                $subSiteAcronym,
                $this->getUser()->getId(),
                $key
            );
        }

        return null;
    }

    /**
     * @param string|\Symfony\Component\Form\FormTypeInterface $type
     * @param null $data
     * @param array $options
     * @param Request|null $request
     * @return Form
     */
    public function createForm(
        $type,
        $data = null,
        array $options = [],
        Request $request = null,
        $defaultMethod = Request::METHOD_POST
    ) {
        if ($request) {
            $options = array_merge($options, [
                'method' => $request->query->get("draft") ?
                    $request->getMethod() :
                    $defaultMethod,
            ]);
        }

        return parent::createForm($type, $data, $options);
    }

    /**
     * @return \ComitiumSuite\Bundle\CoreBundle\Service\AutoSaveDraftHandler|object
     */
    protected function autoSaveDraftHandler()
    {
        return $this->get("cs.handler.auto_save_draft");
    }

    /**
     * @param $entity
     */
    protected function handleGuestUserPermissions($entity)
    {
        if ($this->getUser() instanceof UserInterface && $entity instanceof ContentInterface) {
            if ($this->getUser()->isGuest()) {
                $isUnPublished = $this
                    ->get("cs.manager.state")
                    ->isUnPublished($entity);

                if ($isUnPublished === true && $entity->getUser() !== $this->getUser()) {
                    throw new AccessDeniedHttpException();
                }
            }
        }
    }

    /**
     * @param null $localeCode
     * @return $this|\Comitium5\ApiClientBundle\Provider\ApiProvider|object
     * @throws EntityNotFoundException
     * @throws \Doctrine\ORM\ORMException
     * @throws \Exception
     */
    protected function handleApiClient($localeCode = null)
    {
        $subSite = $this->getSubsite();

        $client = $this
            ->get("designer.api")
            ->buildClient(
                $subSite->getSite()->getPrefix(),
                $subSite->getAcronym(),
                $localeCode ? $localeCode : $this->getReferencedSubsiteDefaultLocale()->getCode()
            );

        return $client;
    }

    /**
     * @param $results
     *
     * @return array
     * @throws \Exception
     */
    protected function parseSearchResults($results)
    {
        if (!isset($results)) {
            return [];
        }

        $elements = [];
        $translator = $this->get('translator');
        $icoUtils   = new IcoUtils();

//        $mappedConfigTypes = TypesHelper::supported();

        /**
         * @var SearchEntityObject $result
         */
        foreach ($results as $result) {

//            $entityClass = $mappedConfigTypes[$result["_type"]];

//            $result["entityClass"] = $entityClass;
            $element["entityId"]      = $result->getId();
            $element['entityType']    = $result->getSelfContentType();
            $element['subSite']       = $result->getSubsite();
            $element['publishedDate'] = $result->getPublishDate();
            $element['title']         = $result->getTitle();

            /*
            $entity = $this
                ->get("cs_core.orm.entity_manager")
                ->getRepository($result['entityClass'])
                ->find($result['entityId']);

            if ($entity === null) {
                continue;
            }
            */

            /*
            $isPublishedForFuture = false;

            if ($entity instanceof ContentInterface) {
                $publishedAt = $entity->getPublishedAt();
                if ($publishedAt instanceof \DateTime) {
                    $isPublishedForFuture = $publishedAt > new \DateTime();
                }
            }
             */
            $isPublishedForFuture = $result->getPublishDate() > new \DateTime();

            $element['isPublishedForFuture'] = $isPublishedForFuture;

//            $element = $result;

//            $transKey = $icoUtils->icoTranslatorKey(Utils::getEntityNameType($result['entityClass']));
//            $iconText = $translator->trans($transKey);
//            $iconText = "foo";

//            if (!empty($result->getSelfContentType())) {
//                $ico = $icoUtils->icoByContentType($result->getSelfContentType());
//            } else {
//                $ico = $icoUtils->icoByNamespace($result['entityClass']);
//            }

            /*
            $element['redirectUrl'] = $this->generateUrl(
                'content_search_redirect_url',
                [
                    'namespace' => $result['entityClass'],
                    'id'        => $result['entityId'],
                ]
            );
            */
            $element['redirectUrl'] = "foo.com";

            /*
            if ($entity instanceof StatefulInterface) {
                if ($entity->getState() instanceof StateInterface) {
                    $element["state"] = [
                        "name"  => $entity->getState()->getName(),
                        "title" => $translator->trans("workflow.states." . $entity->getState()->getName()),
                    ];
                }
            } elseif ($entity instanceof EnabledInterface) {
                $element["state"] = [
                    "name" => $entity->isEnabled() ?
                        StateBehavioursNames::PUBLISHED :
                        StateBehavioursNames::UNPUBLISHED,
                    "title" => $entity->isEnabled() ?
                        $translator->trans("cs_common_base.search.label.enabled"):
                        $translator->trans("cs_common_base.search.label.disabled")
                ];
            }
            */
            $element["state"] = [
                "name" => $result->isSearchable() ?
                    "published" :
                    "unpublished",
                "title" => $result->isSearchable() ?
                    $translator->trans("cs_common_base.search.label.enabled"):
                    $translator->trans("cs_common_base.search.label.disabled")
            ];

            /*
            $element['relatedContentCount'] = 0;

            if ($entity instanceof RelatedContentCollectionInterface) {
                $element['relatedContentCount'] = $entity->getRelatedContents()->count();
            }
            */
            $element['relatedContentCount'] = $result->getUsages();

            /*
            $element['publicUrl'] = "";

            if ($entity instanceof SelfContentTypeInterface) {
                $element['publicUrl'] = $this->get("cs.provider.routing")->generate($entity, true);
            }
            */
            $element['publicUrl'] = $result->getPermalink();

            $element['icon'] = '';
            $element['icon_text'] = '';
            $element['icon_html'] = sprintf('<span class="info-icon"></span><i class="%s"></i> %s', $element['icon'], $element['icon_text']);
//            $element['uuid'] = $entity->getUuid();
            $element['uuid'] = $result->getUuid();

            $element["editUrl"] = "#";
            $element["publishedAt"] = "-";

            /*
            if ($entity instanceof PublishDateInterface) {
                if ($entity->getPublishedAt()) {
                    $element["publishedAt"] = $this
                        ->get("time.templating.helper.time")
                        ->diff($entity->getPublishedAt());
                }
            }
            */
            $element["publishedAt"] = $result->getPublishDate();

            /*
            if ($entity instanceof ContentSearchItemInterface) {
                $element["editUrl"] = $this->generateUrl($entity::getRoute(), $entity->getRouteParams());
                $element['redirectUrl'] = $element["editUrl"];
            }
            */
            $element["editUrl"] = "editUrl.com";
            $element["redirectUrl"] = "redirectUrl.com";

            $element['serialized'] = json_encode($element);

            $elements[] = $element;
        }

        return $elements;
    }

    /**
     * @param Request $request
     * @param array   $excludedContentTypes
     *
     * @return mixed
     */
    protected function buildSearchOptions(Request $request, $excludedContentTypes = [])
    {
        $options['locale']  = $request->query->get('locale', null);
        $options['page']  = $request->query->get('page', 1);
        $options['limit'] = $request->query->get('limit', 5);
        $options['sort'] = $request->get('order') === self::SORT_DATE ? new SearchOrderObject("creationDate", SearchOrderObject::ORDER_DESCENDANT) : null;

        $type = $request->query->get('type', null);
        $state = $request->query->get('state', null);
        $entityId = $request->query->get('entity_id', null);
        $excludedEntityId = $request->query->get('exclude_entity_id', null);
        $excludedTypes = $request->query->get('excluded-content', $excludedContentTypes);

        if ($type) {
            $types = explode(",", $type);

            foreach ($types as $type) {
                $options['content_type']['include'][] = $type;
            }
        }

        if ($state) {
            $states = explode(",", $state);
            foreach ($states as $s) {
                $options['state_id']['include'][] = $s;
            }
        }

        if ($entityId) {
            $options['entity_id']['include'] = [$entityId];
        }

        if ($excludedEntityId) {
            $options['entity_id']['exclude'] = [$excludedEntityId];
        }

        if ($excludedTypes) {
            if (!is_array($excludedTypes)) {
                $excludedTypes = explode(',', $excludedTypes);
            }

            $options['content_type']['exclude'] = $excludedTypes;
        }

        return $options;
    }
}
