<?php declare(strict_types=1);

namespace Newland\Toubiz\Search\Neos\Backend\ElasticSearch;

use Flowpack\ElasticSearch\Domain\Model\AbstractType;
use Neos\Flow\Annotations as Flow;
use function Safe\json_encode;

class RecordBulkModifier
{

    /**
     * @var int|null
     * @Flow\InjectConfiguration(package="Newland.Toubiz.Search.Neos", path="elastic.bulkOperationBatchSize")
     */
    protected $batchSize;

    /**
     * @var mixed[]
     */
    protected $queue = [];

    /** @var AbstractType */
    protected $type;

    public function injectType(ObjectTypeFactory $factory): void
    {
        $this->type = $factory->getType();
    }

    public function updateOrCreate(array $indexContent, string $identifier): void
    {
        $this->queue[] = [
            [ 'index' => [ '_id' => $identifier ] ],
            $indexContent
        ];
        $this->flushIfQueueFull();
    }

    public function remove(string $identifier): void
    {
        $this->queue[] = [
            [ 'delete' => [ '_id' => $identifier ] ]
        ];
        $this->flushIfQueueFull();
    }

    public function flush(): void
    {
        if (\count($this->queue) === 0) {
            return;
        }

        $dataItems = [];
        foreach ($this->queue as $terms) {
            foreach ($terms as $term) {
                $dataItems[] = json_encode($term);
            }
        }

        $this->type->request('POST', '/_bulk', [], implode("\n", $dataItems) . "\n");
        $this->queue = [];
    }

    private function flushIfQueueFull(): void
    {
        if (\count($this->queue) < ($this->batchSize ?: 1000)) {
            return;
        }

        $this->flush();
    }
}
