<?php declare(strict_types=1);
namespace Newland\Toubiz\Sync\Neos\Tests\Factory;

/*
 * 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 Newland\Toubiz\Api\ObjectAdapter\Concern\ArticleConstants;
use Newland\Toubiz\Sync\Neos\Domain\Model\Article;
use Newland\Toubiz\Sync\Neos\Domain\Model\ExternalId;
use Newland\Toubiz\Sync\Neos\Domain\Model\Uri;

/**
 * Class ArticleFactory
 *
 * @package Newland\Toubiz\Sync\Neos\Tests\Factory
 * @method Article create(array $properties)
 */
class ArticleFactory extends AbstractFactory
{
    public function make(array $properties = [])
    {
        $article = new Article();

        $article->setOriginalId($properties['originalId'] ?? $this->faker->uuid);
        $article->setMainType($properties['mainType'] ?? random_int(0, 5));
        $article->setName($properties['name'] ?? $this->faker->name);
        $article->setProcessedName($properties['name'] ?? $this->faker->name);
        $article->setAbstract($properties['abstract'] ?? $this->faker->text);
        $article->setDescription($properties['description'] ?? $this->faker->text);
        $article->setClient($properties['client'] ?? $this->faker->word);
        $article->setLongitude($properties['longitude'] ?? $this->faker->longitude);
        $article->setLatitude($properties['latitude'] ?? $this->faker->latitude);

        $article->setFacebookUri($properties['facebookUri'] ?? $this->faker->url);
        $article->setInstagramUri($properties['instagramUri'] ?? $this->faker->url);
        $article->setYoutubeUri($properties['youtubeUri'] ?? $this->faker->url);
        $article->setFlickrUri($properties['flickrUri'] ?? $this->faker->url);
        $article->setWikipediaUri($properties['wikipediaUri'] ?? $this->faker->url);
        $article->setDetailUri($properties['detailUri'] ?? null);
        $article->setAverageRating($properties['averageRating'] ?? random_int(0, 100));
        $article->setNumberOfRatings($properties['numberOfRatings'] ?? random_int(0, 100));
        $article->setUpdatedAt($properties['updatedAt'] ?? new \DateTime());
        $article->setLanguageGrouping($properties['languageGrouping'] ?? $article->getOriginalId());

        $article->setSourceSystem($properties['sourceSystem'] ?? $this->faker->name);

        if (array_key_exists('openingTimes', $properties)) {
            $article->setOpeningTimes($properties['openingTimes']);
        }
        if (array_key_exists('openingTimesFormat', $properties)) {
            $article->setOpeningTimesFormat($properties['openingTimesFormat']);
        }
        if (array_key_exists('categories', $properties)) {
            $categories = is_array($properties['categories']) ? new ArrayCollection($properties['categories']) :
                $properties['categories'];
            $article->setCategories($categories);
        }
        if (array_key_exists('relatedLists', $properties)) {
            $article->setRelatedLists($properties['relatedLists']);
        }
        if (array_key_exists('language', $properties)) {
            $article->setLanguage($properties['language']);
        }
        if (array_key_exists('mainAddress', $properties)) {
            $article->setMainAddress($properties['mainAddress']);
        }
        if (array_key_exists('addresses', $properties)) {
            $addresses = is_array($properties['addresses']) ? new ArrayCollection($properties['addresses']) :
                $properties['addresses'];
            $article->setAddresses($addresses);
        }
        if (array_key_exists('files', $properties)) {
            $files = is_array($properties['files']) ? new ArrayCollection($properties['files']) : $properties['files'];
            $article->setFiles($files);
        }
        if (array_key_exists('media', $properties)) {
            $media = is_array($properties['media']) ? new ArrayCollection($properties['media']) : $properties['media'];
            $article->setMedia($media);
        }
        if (array_key_exists('attributes', $properties)) {
            $attributes = is_array($properties['attributes']) ? new ArrayCollection($properties['attributes']) :
                $properties['attributes'];
            $article->setAttributes($attributes);
            foreach ($attributes as $attribute) {
                $attribute->setArticle($article);
            }
        }
        if (array_key_exists('cities', $properties)) {
            $properties['cities'] = is_array($properties['cities']) ? new ArrayCollection($properties['cities']) : $properties['cities'];
            $article->setCities($properties['cities']);
        }
        if (array_key_exists('persistenceObjectIdentifier', $properties)) {
            $article->setPersistenceObjectIdentifier($properties['persistenceObjectIdentifier']);
        }
        foreach ($properties['externalIds'] ?? [] as $idProperties) {
            $externalId = new ExternalId();
            $externalId->setId($idProperties['id']);
            $externalId->setType($idProperties['type']);
            $this->persistenceManager->add($externalId);
            $article->getExternalIds()->add($externalId);
        }

        if ($article->getMainType() === ArticleConstants::TYPE_CITY) {
            $article->setCityData(
                $properties['cityData'] ??
                (new CityDataFactory($this->objectManager))->make([ ])
            );
        }

        if (($properties['starClassifications'] ?? false) && is_array($properties['starClassifications'])) {
            $article->setStarClassifications(new ArrayCollection($properties['starClassifications']));
        }

        if (array_key_exists('urlIdentifier', $properties)) {
            $article->setUrlIdentifier($properties['urlIdentifier']);
        }

        $bookingUris = new ArrayCollection($properties['bookingUris'] ?? []);
        $article->setBookingUris($bookingUris);
        foreach ($bookingUris as $bookingUri) {
            /** @var Uri $bookingUri */
            $bookingUri->setArticleAsBookingUri($article);
        }

        $article->setHidden($properties['hidden'] ?? false);
        return $article;
    }
}
