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

/*
 * 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 Doctrine\Common\Collections\Collection;
use Neos\Flow\Annotations as Flow;
use Doctrine\ORM\Mapping as ORM;
use Newland\Toubiz\Sync\Neos\EmptyCheck;
use Newland\Toubiz\Sync\Neos\Orm\Uuid\CustomUuidGeneration;
use Newland\Toubiz\Sync\Neos\Orm\Uuid\UuidGenerator;
use Newland\Toubiz\Sync\Neos\Translation\TranslatableEntity;
use Ramsey\Uuid\UuidInterface;

/**
 * An address.
 *
 * @ORM\Table(indexes={
 *      @ORM\Index(name="newland_toubiz_sync_neos_address_import_ident", columns={"originalid"})
 * })
 *
 * @Flow\Entity
 */
class Address extends AbstractEntity implements EmptyCheck, CustomUuidGeneration
{
    use TranslatableEntity;

    public function generateUuid(): UuidInterface
    {
        return UuidGenerator::uuidFromProperties(
            [ $this->originalId, $this->language ]
        );
    }

    /**
     * @ORM\ManyToMany(
     *     targetEntity="\Newland\Toubiz\Sync\Neos\Domain\Model\Article",
     *      mappedBy="addresses",
     *     fetch="LAZY"
     * )
     * @var Collection<int, Article>
     */
    protected $articles;

    /**
     * @ORM\OneToMany(
     *     targetEntity="\Newland\Toubiz\Sync\Neos\Domain\Model\Article",
     *     mappedBy="mainAddress",
     *     fetch="LAZY"
     * )
     * @var Collection<int, Article>
     */
    protected $articlesAsMainAddress;

    /**
     * @ORM\OneToMany(
     *     targetEntity="\Newland\Toubiz\Sync\Neos\Domain\Model\Event",
     *     mappedBy="location",
     *     fetch="LAZY"
     * )
     * @var Collection<int, Event>
     */
    protected $eventsAsLocation;

    /**
     * @ORM\OneToMany(
     *     targetEntity="\Newland\Toubiz\Sync\Neos\Domain\Model\Event",
     *      mappedBy="organizer",
     *      fetch="LAZY"
     * )
     * @var Collection<int, Event>
     */
    protected $eventsAsOrganizer;

    /**
     * @ORM\Column(nullable=true)
     * @var string|null
     */
    protected $name;

    /**
     * @ORM\Column(nullable=true)
     * @var string|null
     */
    protected $firstName;

    /**
     * @ORM\Column(nullable=true)
     * @var string|null
     */
    protected $lastName;

    /**
     * @ORM\Column(nullable=true)
     * @var string|null
     */
    protected $street;

    /**
     * @ORM\Column(nullable=true)
     * @var string|null
     */
    protected $zip;

    /**
     * @ORM\Column(nullable=true)
     * @var string|null
     */
    protected $city;

    /**
     * @ORM\Column(nullable=true)
     * @var string|null
     */
    protected $country;

    /**
     * @ORM\Column(nullable=true)
     * @var string|null
     */
    protected $phoneNumber;

    /**
     * @ORM\Column(nullable=true)
     * @var string|null
     */
    protected $faxNumber;

    /**
     * @ORM\Column(nullable=true)
     * @var string|null
     */
    protected $emailAddress;

    /**
     * @ORM\Column(type="text", nullable=true)
     * @var string|null
     */
    protected $websiteAddress;

    /**
     * @ORM\Column(nullable=true)
     * @var float|null
     */
    protected $latitude;

    /**
     * @ORM\Column(nullable=true)
     * @var float|null
     */
    protected $longitude;

    public function __construct()
    {
        $this->articles = new ArrayCollection();
        $this->articlesAsMainAddress = new ArrayCollection();
        $this->eventsAsLocation = new ArrayCollection();
        $this->eventsAsOrganizer = new ArrayCollection();
    }

    public function setName(?string $name): void
    {
        $this->name = $name;
    }

    public function getName(): ?string
    {
        return $this->name;
    }

    public function setFirstName(?string $firstName): void
    {
        $this->firstName = $firstName;
    }

    public function getFirstName(): ?string
    {
        return $this->firstName;
    }

    public function setLastName(?string $lastName): void
    {
        $this->lastName = $lastName;
    }

    public function getLastName(): ?string
    {
        return $this->lastName;
    }

    public function setStreet(?string $street): void
    {
        $this->street = $street;
    }

    public function getStreet(): ?string
    {
        return $this->street;
    }

    public function setZip(?string $zip): void
    {
        $this->zip = $zip;
    }

    public function getZip(): ?string
    {
        return $this->zip;
    }

    public function setCity(?string $city): void
    {
        $this->city = $city;
    }

    public function getCity(): ?string
    {
        return $this->city;
    }

    public function setPhoneNumber(?string $phoneNumber): void
    {
        $this->phoneNumber = $phoneNumber;
    }

    public function getPhoneNumber(): ?string
    {
        return $this->phoneNumber;
    }

    public function setFaxNumber(?string $faxNumber): void
    {
        $this->faxNumber = $faxNumber;
    }

    public function getFaxNumber(): ?string
    {
        return $this->faxNumber;
    }

    public function getEmailAddress(): ?string
    {
        return $this->emailAddress;
    }

    public function setEmailAddress(?string $emailAddress): void
    {
        $this->emailAddress = $emailAddress;
    }

    public function getWebsiteAddress(): ?string
    {
        return $this->websiteAddress;
    }

    public function setWebsiteAddress(?string $websiteAddress): void
    {
        $this->websiteAddress = $websiteAddress;
    }

    public function getCountry(): ?string
    {
        return $this->country;
    }

    public function setCountry(?string $country): void
    {
        $this->country = $country;
    }

    public function getLatitude(): ?float
    {
        return $this->latitude;
    }

    public function setLatitude(?float $latitude): void
    {
        $this->latitude = $latitude;
    }

    public function hasLatitude(): bool
    {
        return !empty($this->latitude);
    }

    public function getLongitude(): ?float
    {
        return $this->longitude;
    }

    public function setLongitude(?float $longitude): void
    {
        $this->longitude = $longitude;
    }

    public function hasLongitude(): bool
    {
        return !empty($this->longitude);
    }

    public function getHasGeocoordinates(): bool
    {
        return ($this->hasLatitude() && $this->hasLongitude());
    }

    public function getFullAddress(): string
    {
        $parts = [
            $this->name,
            $this->firstName . ' ' . $this->lastName,
            $this->street,
            $this->zip,
            $this->city,
        ];

        return implode(', ', array_filter($parts));
    }

    public function isEmpty(): bool
    {
        return empty($this->name)
            && empty($this->emailAddress)
            && empty($this->street)
            && empty($this->phoneNumber);
    }

    /** @return Collection<int, Article> */
    public function getArticles(): Collection
    {
        return $this->articles;
    }

    /** @param Collection<int, Article> $articles */
    public function setArticles(Collection $articles): void
    {
        $this->articles = $articles;
    }

    /** @return Collection<int, Article> */
    public function getArticlesAsMainAddress(): Collection
    {
        return $this->articlesAsMainAddress;
    }

    /** @param Collection<int, Article> $articlesAsMainAddress */
    public function setArticlesAsMainAddress(Collection $articlesAsMainAddress): void
    {
        $this->articlesAsMainAddress = $articlesAsMainAddress;
    }

    /** @return Collection<int, Event> */
    public function getEventsAsLocation(): Collection
    {
        return $this->eventsAsLocation;
    }

    /** @param  Collection<int, Event> $eventsAsLocation */
    public function setEventsAsLocation(Collection $eventsAsLocation): void
    {
        $this->eventsAsLocation = $eventsAsLocation;
    }

    /** @return Collection<int, Event> */
    public function getEventsAsOrganizer(): Collection
    {
        return $this->eventsAsOrganizer;
    }

    /** @param  Collection<int, Event> $eventsAsOrganizer */
    public function setEventsAsOrganizer(Collection $eventsAsOrganizer): void
    {
        $this->eventsAsOrganizer = $eventsAsOrganizer;
    }
}
