<?php

namespace KupShop\ArticlesBundle\Feed;

use Doctrine\Common\Collections\ArrayCollection;
use KupShop\ArticlesBundle\Wrapper\ArticleWrapper;
use KupShop\FeedGeneratorBundle\Feed\ConfigurableFeedTrait;
use KupShop\FeedGeneratorBundle\Feed\IConfigurableFeed;
use KupShop\FeedsBundle\Feed\IFeed;
use KupShop\I18nBundle\Translations\ArticlesTranslation;
use Query\Translation;

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

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

    /** @var string */
    public static $alias = 'Články';

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

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

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

    public function __construct(ArticleWrapper $articleWrapper)
    {
        $this->objectWrapper = $articleWrapper;
    }

    public function getQuery(int $feedID, $feedRow): \Query\QueryBuilder
    {
        $qb = sqlQueryBuilder()->select('a.*')->from('articles', 'a')
            ->andWhere(Translation::coalesceTranslatedFields(ArticlesTranslation::class))
            ->orderBy('a.id');
        if (($feedRow['settings']['filter']['includeHidden'] ?? null) != 'Y') {
            $qb->andWhere("a.figure='Y'"); // default: select only visible articles (when includeHidden is NOT set to 'Y')
        }
        foreach ($this->specs as $spec) {
            $qb->andWhere($spec);
        }
        $this->query = $qb;

        return $qb;
    }

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

            return '';
        };
    }

    public function getData(array $feedRow, ?int $limit = null): \Generator
    {
        $settingsJson = ($feedRow['settings'] ?? null);
        if ($settingsJson) {
            $feedRow['settings'] = json_decode_strict($settingsJson, true);
        }
        $qb = $this->query ?? $this->getQuery($feedRow['id'], $feedRow);

        $countQuery = (clone $qb)
            ->select('count(a.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);
            $articles = new ArrayCollection();
            foreach ($qb->execute() as $row) {
                $articles->set($row['id'], (object) $row); // cast to (object) to force reference
            }
            $this->objectWrapper->setArticles($articles);
            foreach ($articles as $article) {
                yield $this->prepareSingleObject($article);
            }
        }
    }
}
