<?php

namespace Comitium5\DesignerBundle\Repository\Search;

use Comitium5\CommonWidgetsBundle\Search\ElasticResultParser;
use Comitium5\DesignerBundle\Factory\Search\Result\ElasticSearchResultFactory;
use Comitium5\DesignerBundle\Factory\Search\Suggest\ElasticSearchQueryFactory;
use Comitium5\DesignerBundle\Model\Interfaces\SearchClientInterface;
use Comitium5\DesignerBundle\Model\Interfaces\SearchRepositoryInterface;
use Comitium5\DesignerBundle\ValueObjects\SearchQueryObject;
use Comitium5\DesignerBundle\ValueObjects\SearchResultObject;
use Elastica\Search;

/**
 * Class ElasticSearchRepository
 *
 * @author David Carrascosa <david@bab-soft.com>
 * @package Comitium5\DesignerBundle\Repository\Search
 */
class ElasticSearchRepository implements SearchRepositoryInterface
{
    /**
     * @var SearchClientInterface
     */
    protected $searchClientInterface;

    /**
     * ElasticSearchRepository constructor.
     *
     * @param SearchClientInterface $searchClientInterface
     */
    public function __construct(
        SearchClientInterface $searchClientInterface
    ) {
        $this->searchClientInterface = $searchClientInterface;
    }

    /**
     * @param SearchQueryObject $searchQueryObject
     *
     * @return SearchResultObject
     * @throws \Exception
     */
    public function search(SearchQueryObject $searchQueryObject): SearchResultObject
    {
        /**
         * @var Search $client
         */
        $client = $this
            ->searchClientInterface
            ->getClient();

        $this->addIndexes($searchQueryObject, $client);

        $client->addType($searchQueryObject->getContentType());

        $factory = new ElasticSearchQueryFactory();

        $results = $client->search(
            $factory->create($searchQueryObject),
            ['limit' => $searchQueryObject->getLimit()]
        );

        return ElasticSearchResultFactory::create(
            ElasticResultParser::parser($results)
        );
    }

    /**
     * @param SearchQueryObject $searchQueryObject
     * @param Search $client
     *
     * @throws \Exception
     */
    protected function addIndexes(SearchQueryObject $searchQueryObject, Search $client): void
    {
        foreach ($searchQueryObject->getSubsites() as $subsite) {
            $client->addIndex($subsite->getAcronym());
        }
    }
}
