<?php

namespace KupShop\CatalogBundle\Feed;

use Doctrine\Common\Collections\ArrayCollection;
use KupShop\CatalogBundle\Feed\Wrapper\ProducerWrapper;
use KupShop\FeedGeneratorBundle\Feed\ConfigurableFeedTrait;
use KupShop\FeedGeneratorBundle\Feed\IConfigurableFeed;
use KupShop\FeedsBundle\Feed\IFeed;
use Query\Operator;
use Query\QueryBuilder;

class ProducerConfigurableFeed implements IFeed, IConfigurableFeed
{
    use \DatabaseCommunication;
    use ConfigurableFeedTrait;

    /** @var string */
    public static $type = 'producerConfigurable';

    /** @var string */
    public static $alias = 'Výrobci';

    /** @var string */
    public static $objectType = 'producer';

    /** @var \Query\QueryBuilder */
    protected $query;

    public static function isAllowed(): bool
    {
        return (bool) findModule(\Modules::PRODUCERS);
    }

    public function __construct(ProducerWrapper $producerWrapper)
    {
        $this->objectWrapper = $producerWrapper;
    }

    public function getQuery(): QueryBuilder
    {
        $qb = sqlQueryBuilder()->select('pr.*')
            ->from('producers', 'pr')
            ->where(Operator::equals(['pr.active' => 'Y']))
            ->orderBy('pr.position');

        foreach ($this->specs as $spec) {
            $qb->andWhere($spec);
        }

        $this->query = $qb;

        return $qb;
    }

    public function filterByObjectID($objectID): void
    {
        $this->specs[] = function (QueryBuilder $qb) use ($objectID) {
            $qb->andWhere('pr.id=:producer_id')->setParameter('producer_id', $objectID);

            return '';
        };
    }

    public function getData(array $feedRow, ?int $limit = null): \Generator
    {
        $qb = $this->query ?? $this->getQuery();

        $countQuery = (clone $qb)
            ->select('count(pr.id) AS c')
            ->resetQueryPart('groupBy');
        $count = (int) $countQuery->execute()->fetch()['c'];

        // use batching only if limit is NOT set
        $iterationLimit = isset($limit) ? 1 : ($count / (float) static::$batchSize);
        for ($i = 0; $i < $iterationLimit; $i++) {
            $qb->setFirstResult($i * static::$batchSize);
            $qb->setMaxResults($limit ?? static::$batchSize);
            $producers = new ArrayCollection();
            foreach ($qb->execute() as $row) {
                $producers->set($row['id'], (object) $row); // cast to (object) to force reference
            }
            $this->objectWrapper->setProducers($producers);
            foreach ($producers as $producer) {
                yield $this->prepareSingleObject($producer);
            }
        }
    }
}
