<?php
namespace Whater\Domain\Zones\Model;
use BornFree\TacticianDomainEvent\Recorder\ContainsRecordedEvents;
use BornFree\TacticianDomainEvent\Recorder\EventRecorderCapabilities;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Location\Coordinate;
use Location\Ellipsoid;
use Location\Formatter\Polygon\GeoJSON;
use Location\Polygon as LocationPolygon;
use Ramsey\Uuid\Uuid;
use Whater\Domain\Common\Exception\InvalidUUIDException;
use LongitudeOne\Spatial\PHP\Types\Geometry\Polygon;
use Whater\Domain\Whater\Model\DistributionNetwork;
use Whater\Domain\Whater\Model\WhaterOrganization;
use Whater\Domain\Zones\Event\TownLocationPolygonWasUpdate;
/**
* Class TownLocation - Localizaciones - (localidades en sinac)
*
* @package Whater\Domain\Zones\Model
*/
class TownLocation implements ContainsRecordedEvents
{
use EventRecorderCapabilities;
// const IDS_SINAC_LOCALIDAD = 'sinac_codLocalidad';
const TLT_URBAN_ZONE = 'TLT_URBAN_ZONE';
const TLT_INDUSTRIAL_ZONE = 'TLT_INDUSTRIAL_ZONE';
/**
* @var string
*/
private $uuid;
/**
* @var string
*/
private $slug;
/**
* @var string
*/
private $name;
/**
* @var string
*/
private $townLocationType;
/**
* @var array
*/
private $externalIds;
/**
* @var int
*/
private $population;
/**
* @var float
*/
private $latitude;
/**
* @var float
*/
private $longitude;
/**
* @var Polygon
*/
private $geometryPolygon;
/**
* @var Country
*/
private $country;
/**
* @var CountryArea
*/
private $countryArea;
/**
* @var Town
*/
private $town;
/**
* @var DistributionNetwork
*/
private $distributionNetwork;
/**
* @var Collection
*/
private $whaterPoints;
/**
* @var \DateTime
*/
private $createdAt;
/**
* @var \DateTime
*/
private $updatedAt;
/**
* @var \DateTime
*/
private $sinacSynchonizationAt;
/**
* @var Collection
*/
private $ubications;
/**
* @var Collection
*/
private $establishments;
/**
* @var WhaterOrganization
*/
private $whaterOrganization;
/**
* @var Collection
*/
private $ownershipRequests;
/**
* @param string $townLocationId
* @param Country $country
* @param CountryArea $countryArea
* @param Town $town
* @param DistributionNetwork $distributionNetwork
* @param string $name
* @param float $latitude
* @param float $longitude
* @param string $slug
* @param array $externalIds
*/
public function __construct(
string $townLocationId = null,
Country $country,
CountryArea $countryArea,
Town $town,
DistributionNetwork $distributionNetwork = null,
string $name,
string $townLocationType,
float $latitude,
float $longitude,
string $slug = null,
array $externalIds = []
) {
try {
$this->uuid = Uuid::fromString($townLocationId ?: Uuid::uuid4())->toString();
} catch (\InvalidArgumentException $e) {
throw new InvalidUUIDException();
}
$this->country = $country;
if ($countryArea != null) {
$this->countryArea = $countryArea;
$this->country = $countryArea->country();
}
$this->town = $town;
$this->distributionNetwork = $distributionNetwork;
$this->slug = $slug;
$this->name = $name;
$this->townLocationType = $townLocationType;
$this->externalIds = $externalIds;
$this->latitude = $latitude;
$this->longitude = $longitude;
$this->geometryPolygon = new Polygon([[
[$this->longitude + 0.005, $this->latitude + 0.005],
[$this->longitude + 0.005, $this->latitude - 0.005],
[$this->longitude - 0.005, $this->latitude - 0.005],
[$this->longitude - 0.005, $this->latitude + 0.005],
[$this->longitude + 0.005, $this->latitude + 0.005]
]]);
$this->whaterPoints = new ArrayCollection();
$this->ubications = new ArrayCollection();
$this->establishments = new ArrayCollection();
$this->createdAt = new \DateTime();
$this->updatedAt = new \DateTime();
$this->ownershipRequests = new ArrayCollection();
}
public function updateTownLocationData(
string $name,
string $slug = null,
int $population = null,
WhaterOrganization $whaterOrganization = null,
DistributionNetwork $distributionNetwork = null
) {
$this->name = $name;
$this->slug = $slug;
$this->population = $population;
$this->whaterOrganization = $whaterOrganization;
$this->distributionNetwork = $distributionNetwork;
$this->updatedAt = new \DateTime();
}
public function editPolygon(
Polygon $geometryPolygon
) {
$this->geometryPolygon = $geometryPolygon;
$this->record(new TownLocationPolygonWasUpdate($this));
}
public function editCenter(
float $latitude = null,
float $longitude = null
) {
if ($latitude != null) {
$this->latitude = $latitude;
}
if ($longitude != null) {
$this->longitude = $longitude;
}
}
public function updatesinacSynchonizationAt(\DateTime $sinacSynchonizationAt)
{
$this->sinacSynchonizationAt = $sinacSynchonizationAt;
}
/**
* @return string
*/
public function id(): string
{
return $this->uuid;
}
/**
* @return string
*/
public function name(): string
{
return $this->name;
}
/**
* @return string
*/
public function townLocationType(): string
{
return $this->townLocationType;
}
/**
* @return float|null
*/
public function latitude(): ?float
{
return $this->latitude;
}
/**
* @return float|null
*/
public function longitude(): ?float
{
return $this->longitude;
}
/**
* @return Polygon
*/
public function geometryPolygon(): ?Polygon
{
return $this->geometryPolygon;
}
/**
* @return LocationPolygon
*/
public function locationPolygon(): ?LocationPolygon
{
if ($this->geometryPolygon() != null) {
$pol = new LocationPolygon();
$points = $this->geometryPolygon()->toArray();
foreach ($points[0] as $point) {
$lat = $point[1];
$long = $point[0];
$pol->addPoint(new Coordinate($lat, $long, Ellipsoid::createDefault()));
}
return $pol;
}
return null;
}
public function getGeoJsonPolygon(): ?string
{
if ($this->geometryPolygon() != null) {
$geoJsonCoordinates = [];
// Recorre los anillos (exterior + huecos si existen)
foreach ($this->geometryPolygon()->getRings() as $ring) {
$ringCoordinates = [];
// Recorre los puntos del anillo
foreach ($ring->getPoints() as $point) {
$ringCoordinates[] = [$point->getLongitude(), $point->getLatitude()];
}
// Cierra el anillo si no está cerrado
if ($ringCoordinates[0] !== $ringCoordinates[count($ringCoordinates) - 1]) {
$ringCoordinates[] = $ringCoordinates[0];
}
// Añade el anillo a las coordenadas del GeoJSON
$geoJsonCoordinates[] = $ringCoordinates;
}
// Construye el GeoJSON
$geoJson = [
"type" => "Polygon",
"coordinates" => $geoJsonCoordinates
];
return json_encode($geoJson, JSON_PRETTY_PRINT);
}
return null;
}
/**
* @return string
*/
public function slug(): ?string
{
return $this->slug;
}
/**
* @return integer|null
*/
public function population(): ?int
{
return $this->population;
}
/**
* @return array
*/
public function externalIds(): array
{
return $this->externalIds;
}
/**
* @return Country
*/
public function country(): Country
{
return $this->country;
}
/**
* @return CountryArea|null
*/
public function countryArea(): ?CountryArea
{
return $this->countryArea;
}
/**
* @return Town
*/
public function town(): Town
{
return $this->town;
}
/**
* @return DistributionNetwork
*/
public function distributionNetwork(): ?DistributionNetwork
{
return $this->distributionNetwork;
}
/**
* @return Collection
*/
public function whaterPoints(): Collection
{
return $this->whaterPoints;
}
/**
* @return Collection
*/
public function ubications(): Collection
{
return $this->ubications;
}
/**
* @return Collection
*/
public function establishments(): Collection
{
return $this->establishments;
}
/**
* @return WhaterOrganization|null
*/
public function whaterOrganization(): ?WhaterOrganization
{
return $this->whaterOrganization;
}
/**
* @return \DateTime
*/
public function createdAt(): \DateTime
{
return $this->createdAt;
}
/**
* @return \DateTime
*/
public function updatedAt(): \DateTime
{
return $this->updatedAt;
}
/**
* @return Collection
*/
public function ownershipRequests(): Collection
{
return $this->ownershipRequests;
}
/**
* @return \DateTime
*/
public function sinacSynchonizationAt(): ?\DateTime
{
return $this->sinacSynchonizationAt;
}
/**
* @return bool
*/
public function equals(TownLocation $town)
{
return $this->id() === $town->id();
}
}