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

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

use Doctrine\Common\Collections\ArrayCollection;
use Neos\Flow\Annotations as Flow;
use Newland\Toubiz\Api\ObjectAdapter\RegionAdapterInterface;
use Newland\Toubiz\Api\ObjectAdapter\SlopeAdapterInterface;
use Newland\Toubiz\Api\ObjectAdapter\TransportationFacilityAdapterInterface;
use Newland\Toubiz\Sync\Neos\Domain\Model\Region;
use Newland\Toubiz\Sync\Neos\Domain\Repository\RegionRepository;

class RegionImporter extends AbstractImporter
{
    /**
     * @Flow\Inject()
     * @var RegionRepository
     */
    protected $regionRepository;

    /**
     * @var Region
     */
    protected $region;


    /**
     * Import method.
     *
     * Persist given data by creating new objects or updating existing ones.
     *
     * @param RegionAdapterInterface $data
     * @return Region
     */
    public function import($data)
    {
        $this->initializeLogger($data, [
            'region' => [
                'externalId' => $data->getExternalId(),
                'name' => $data->getName(),
            ]
        ]);

        $this->data = $data;
        $persisted = $this->fetchRegionOrCreateNew();

        $this->mapSimpleValues();

        if ($persisted) {
            $this->regionRepository->update($this->region);
        } else {
            $this->regionRepository->add($this->region);
        }

        $this->mapSlopes();
        $this->mapTransportationFacilities();
        $this->regionRepository->update($this->region);

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

    /**
     * Maps simple values onto the event.
     *
     * @return void
     */
    protected function mapSimpleValues()
    {
        if (!$this->region->getOriginalId()) {
            $this->region->setOriginalId($this->data->getExternalId());
        }

        $this->region->setName($this->data->getName());
        $this->region->setUpdatedAt($this->data->getUpdatedAt());
        $this->region->setAttributes($this->data->getAttributes());
    }

    /**
     * Maps slopes onto the region.
     *
     * @return void
     */
    protected function mapSlopes()
    {
        $this->updateCollection(
            $this->region->getSlopes(),
            $this->data->getSlopes(),
            function (SlopeAdapterInterface $slopeAdapter) {
                return (new SlopeImporter())->import($slopeAdapter);
            }
        );
    }

    /**
     * Maps transportation facilities onto the region.
     *
     * @return void
     */
    protected function mapTransportationFacilities()
    {
        $this->updateCollection(
            $this->region->getTransportationFacilities(),
            $this->data->getTransportationFacilities(),
            function (TransportationFacilityAdapterInterface $facilityAdapter) {
                return (new TransportationFacilityImporter())->import($facilityAdapter);
            }
        );
    }

    private function fetchRegionOrCreateNew(): bool
    {
        $region = $this->regionRepository->findOneByOriginalId($this->data->getExternalId());
        $persisted = (bool) $region;
        $this->region = $region ?? new Region();
        return $persisted;
    }
}
