<?php

namespace Comitium5\DesignerBundle\Factory\Search\Suggest;

use Comitium5\DesignerBundle\Resolver\Search\Suggest\ElasticSearchQueryFieldsResolver;
use Comitium5\DesignerBundle\ValueObjects\SearchQueryObject;
use Elastica\Query\BoolQuery;
use Elastica\Query\Match;

/**
 * Class ElasticSearchSuggestQueryFactory
 *
 * @author David Carrascosa <david@bab-soft.com>
 * @package Comitium5\DesignerBundle\Factory\Search\Suggest
 */
class ElasticSearchBoolQueryFactory
{
    /**
     * @param SearchQueryObject $object
     *
     * @return BoolQuery
     */
    public function __invoke(SearchQueryObject $object): BoolQuery
    {
        $boolQuery = new BoolQuery();
        $filtersQuery = new BoolQuery();
        $fieldsQuery = new BoolQuery();

        foreach ($object->getFilters() as $filter) {
            $filter($filtersQuery);
        }

        $resolver = new ElasticSearchQueryFieldsResolver();
        $fields = $resolver($object->getContentType());

        if (is_numeric($object->getTerm())) {
            $matchId = new Match();
            $matchId->setFieldQuery('id', $object->getTerm());
            $fieldsQuery->addShould($matchId);
        }

        foreach($fields as $field) {
            $this->matchField(
                $fieldsQuery,
                $object->getTerm(),
                $field
            );
        }

        $boolQuery
            ->addMust($filtersQuery)
            ->addMust($fieldsQuery);

        return $boolQuery;
    }

    /**
     * @param BoolQuery $boolQuery
     * @param string $term
     * @param string $field
     */
    protected function matchField(BoolQuery $boolQuery, string $term, string $field): void
    {
        $match = new Match();
        $match->setFieldQuery($field, $term);
        $match->setFieldAnalyzer($field, 'suggest_analyzer');
        $boolQuery->addShould($match);
    }
}
