<?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 Neos\Flow\Annotations as Flow;
use Newland\Toubiz\Api\ObjectAdapter\RegionAdapterInterface;
use Newland\Toubiz\Sync\Neos\Domain\Model\Region;
use Newland\Toubiz\Sync\Neos\Domain\Repository\RegionRepository;

/**
 * Region importer.
 *
 * @Flow\Scope("singleton")
 */
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->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()
    {
        $slopes = $this->region->getSlopes();
        $slopes->clear();
        foreach ($this->data->getSlopes() as $data) {
            $importer = new SlopeImporter;
            $slope = $importer->import($data);
            if (!$slopes->contains($slope)) {
                $slopes->add($slope);
            }
        }
        $this->region->setSlopes($slopes);
    }

    /**
     * Maps transportation facilities onto the region.
     *
     * @return void
     */
    protected function mapTransportationFacilities()
    {
        $facilities = $this->region->getTransportationFacilities();
        $facilities->clear();
        foreach ($this->data->getTransportationFacilities() as $data) {
            $importer = new TransportationFacilityImporter;
            $facility = $importer->import($data);
            if (!$facilities->contains($facility)) {
                $facilities->add($facility);
            }
        }
        $this->region->setTransportationFacilities($facilities);
    }

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