<?php
namespace Newland\Toubiz\Sync\Neos\Importer;

use Doctrine\Common\Collections\ArrayCollection;
use Newland\Toubiz\Api\ObjectAdapter\PackageAdapterInterface;
use Neos\Flow\Annotations as Flow;
use Newland\Toubiz\Sync\Neos\Domain\Model\Benefit;
use Newland\Toubiz\Sync\Neos\Domain\Model\Medium;
use Newland\Toubiz\Sync\Neos\Domain\Model\Package;
use Newland\Toubiz\Sync\Neos\Domain\Repository\PackageRepository;

/**
 * @Flow\Scope("singleton")
 */
class PackageImporter extends AbstractImporter
{

    /**
     * @var PackageRepository
     * @Flow\Inject()
     */
    protected $packageRepository;
    /**
     * @var string
     */
    protected $client;

    /**
     * Main import method.
     *
     * Must be defined in each implementation.
     *
     * @param PackageAdapterInterface $data
     * @return Package
     */
    public function import($data): Package
    {
        $package = $this->packageRepository->withLanguage($data->getlanguage(), function () use ($data) {
            return $this->packageRepository->findOneByOriginalIdAndClient($data->getExternalId(), $this->client);
        });
        $isNew = $package === null;
        $package = $package ?? new Package();

        $package->setLanguage($data->getLanguage());
        $package->setClient($this->client);
        $this->mapSimpleValues($package, $data);
        $this->mapBenefits($package, $data);
        $this->mapMedia($package, $data);

        if ($isNew) {
            $this->packageRepository->add($package);
        } else {
            $this->packageRepository->update($package);
        }

        $this->persistenceManager->persistAll();
        return $package;
    }

    /**
     * @param string $client
     * @return void
     */
    public function setClient(string $client): void
    {
        $this->client = $client;
    }

    /**
     * @param Package $package
     * @param PackageAdapterInterface $data
     * @return void
     */
    private function mapSimpleValues(Package $package, PackageAdapterInterface $data): void
    {
        $package->setOriginalId($data->getExternalId());
        $package->setName($data->getName());
        $package->setStartingPrice($data->getStartingPrice() ?? 0.0);
        $package->setStartingPriceCurrency($data->getStartingPriceCurrency() ?? '');
        $package->setMinimumNights($data->getMinimumNights() ?? 0.0);
        $package->setDetailUri($data->getDetailUri());
    }

    /**
     * @param Package $package
     * @param PackageAdapterInterface $data
     * @return void
     */
    private function mapBenefits(Package $package, PackageAdapterInterface $data): void
    {
        $newBenefits = new ArrayCollection();
        $oldBenefits = $package->getBenefits();

        foreach ($data->getBenefits() as $index => $benefit) {
            $model = $oldBenefits->get($index) ?: new Benefit();
            $model->setOriginalId($data->getExternalId() . '-' . $index);
            $model->setName($benefit);
            $model->setPackage($package);
            $newBenefits->add($model);
        }

        $package->setBenefits($newBenefits);
    }

    /**
     * @param Package $package
     * @param PackageAdapterInterface $data
     * @return void
     */
    private function mapMedia(Package $package, PackageAdapterInterface $data): void
    {
        $media = [];
        $sourceUri = $data->getPreviewImage();

        if ($sourceUri !== null) {
            $first = $package->getMedia()->first() ?: new Medium();
            $first->setSourceUri($data->getPreviewImage());
            $first->setOriginalId($data->getExternalId() . '-main');
            $media[] = $first;
        }

        $package->setMedia(new ArrayCollection($media));
    }
}
