<?php
namespace Newland\Toubiz\Poi\Neos\Search\Indexer;

/*
 * This file is part of the "toubiz-poi-neos" package.
 *
 * For the full copyright and license information, please read the
 * LICENSE.txt file that was distributed with this source code.
 */

use Neos\Flow\Annotations as Flow;
use Newland\Toubiz\Search\Neos\Indexer\AbstractRecordIndexer;
use Newland\Toubiz\Search\Neos\Indexer\IndexerInterface;
use Newland\Toubiz\Search\Neos\Indexer\IndexRecordModification;
use Newland\Toubiz\Sync\Neos\Domain\Model\Article;
use Newland\Toubiz\Sync\Neos\Domain\PagedDatabaseResult;
use Newland\Toubiz\Sync\Neos\Domain\Repository\ArticleRepository;

/**
 * Article indexer.
 *
 * Indexes articles for the search.
 *
 * @Flow\Scope("singleton")
 */
class ArticleIndexer extends AbstractRecordIndexer implements IndexerInterface
{
    public const SCOPE = 'toubiz_articles';

    /**
     * @var ArticleRepository
     * @Flow\Inject()
     */
    protected $articleRepository;

    /** @var int|null */
    private $total;

    /** @var int */
    private $processed = 0;

    /**
     * Entry point.
     *
     * Indexes article records.
     *
     * @return void
     */
    public function index(): void
    {
        $this->articleRepository->withoutLanguageHandling(function () {
            $this->initializeCounters();
            foreach ($this->articleRepository->findAll() as $article) {
                $this->indexArticle($article);
                $this->informProgress(++$this->processed, $this->total);
            }
        });
    }

    /**
     * Runs post-index tasks such as cleaning up old records.
     *
     * @return void
     */
    public function postIndex(): void
    {
        $this->searchIndexRepository->deleteObsolete($this->index, static::SCOPE);

        // For legacy systems: Scope used to be classname.
        $this->searchIndexRepository->deleteObsolete($this->index, \get_class($this));
    }

    private function indexArticle(Article $article): void
    {
        $content = [
            $article->getName(),
            $article->getAbstract(),
            $article->getDescription(),
        ];

        $modification = new IndexRecordModification(
            (string) $article->getPersistenceObjectIdentifier(),
            $this->convertToIndexableString($article->getName()),
            $this->convertToIndexableString((string) $article->getAbstract()),
            $this->convertToIndexableString(implode(' ', $content))
        );
        $modification->setLanguage($article->getLanguage())
            ->setScope(static::SCOPE);

        $this->addToIndex($modification);
    }

    private function initializeCounters(): void
    {
        $this->processed = 0;
        $this->total = $this->articleRepository->countAll();
    }
}
