<?php

namespace App\Entity;

use App\Entity\Domain\Stat;
use App\Entity\Domain\TopicTrustFlow;
use App\Entity\Traits\TimestampableTrait;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;
use Symfony\Component\Validator\Constraints as Assert;

/**
 * @ORM\Entity
 * @UniqueEntity("url")
 * @ORM\EntityListeners({"App\EntityListener\DomainListener"})
 */
class Domain implements BroadcastableInterface
{
    use TimestampableTrait;

    /**
     * @ORM\Id()
     * @ORM\GeneratedValue()
     * @ORM\Column(type="integer")
     */
    private $id;

    /**
     * @ORM\Column(type="EnumHttpProtocolType")
     */
    private $protocol;

    /**
     * @ORM\Column(type="string", length=255)
     * @Assert\NotBlank()
     * @Assert\Url()
     */
    private $url;

    /**
     * @ORM\Column(type="datetime", nullable=true)
     */
    private $checkedAt;

    /**
     * @ORM\OneToMany(targetEntity="Campaign", mappedBy="domain")
     */
    private $campaigns;

    /**
     * @ORM\OneToMany(targetEntity="App\Entity\Prospect", mappedBy="domain")
     */
    private $prospects;

    /**
     * @ORM\OneToMany(targetEntity="App\Entity\Domain\Stat", mappedBy="domain", cascade={"persist"}, orphanRemoval=true)
     */
    private $stats;

    /**
     * @ORM\Column(type="EnumDomainUrlType", options={"default" : "ROOTDOMAIN"})
     */
    private $urlType;

    /**
     * @ORM\Column(type="string", length=20, nullable=true)
     */
    private $ip;

    /**
     * @ORM\OneToMany(targetEntity="App\Entity\Domain\TopicTrustFlow", mappedBy="domain", orphanRemoval=true)
     */
    private $topicTrustFlows;

    public function __construct()
    {
        $this->campaigns = new ArrayCollection();
        $this->prospects = new ArrayCollection();
        $this->stats = new ArrayCollection();
        $this->topicTrustFlows = new ArrayCollection();
    }

    public function getId(): ?int
    {
        return $this->id;
    }

    public function getCheckedAt(): ?\DateTimeInterface
    {
        return $this->checkedAt;
    }

    public function setCheckedAt(?\DateTimeInterface $checkedAt): self
    {
        $this->checkedAt = $checkedAt;

        return $this;
    }

    public function addCampaign(Campaign $campaign): self
    {
        if (!$this->campaigns->contains($campaign)) {
            $this->campaigns[] = $campaign;
            $campaign->setDomain($this);
        }

        return $this;
    }

    public function removeCampaign(Campaign $campaign): self
    {
        if ($this->campaigns->contains($campaign)) {
            $this->campaigns->removeElement($campaign);
            // set the owning side to null (unless already changed)
            if ($campaign->getDomain() === $this) {
                $campaign->setDomain(null);
            }
        }

        return $this;
    }

    public function addProspect(Prospect $prospect): self
    {
        if (!$this->prospects->contains($prospect)) {
            $this->prospects[] = $prospect;
            $prospect->addDomain($this);
        }

        return $this;
    }

    public function removeProspect(Prospect $prospect): self
    {
        if ($this->prospects->contains($prospect)) {
            $this->prospects->removeElement($prospect);
            $prospect->removeDomain($this);
        }

        return $this;
    }

    /**
     * @return Collection|Prospect[]
     */
//    public function getProspects(): Collection
//    {
//        return $this->prospects;
//    }

    /**
     * @return Collection
     */
    public function getStats(): Collection
    {
        return $this->stats;
    }

    public function addStat(?Stat $stat): self
    {
        if (!$this->stats->contains($stat)) {
            $this->stats[] = $stat;
            $stat->setDomain($this);
        }

        return $this;
    }

    public function removeStat(Stat $stat): self
    {
        if ($this->stats->contains($stat)) {
            $this->stats->removeElement($stat);
            // set the owning side to null (unless already changed)
            if ($stat->getDomain() === $this) {
                $stat->setDomain(null);
            }
        }

        return $this;
    }

    public function getUrlType()
    {
        return $this->urlType;
    }

    public function setUrlType(string $urlType): self
    {
        $this->urlType = $urlType;

        return $this;
    }

    public function getIp(): ?string
    {
        return $this->ip;
    }

    public function setIp(?string $ip): self
    {
        $this->ip = $ip;

        return $this;
    }

    public function getFullUrl(): string
    {
        return $this->getProtocol().$this->getUrl();
    }

    public function getProtocol()
    {
        return $this->protocol;
    }

    public function setProtocol(string $protocol): self
    {
        $this->protocol = $protocol;

        return $this;
    }

    public function getUrl(): ?string
    {
        return $this->url;
    }

    public function setUrl(string $url): self
    {
        $this->url = $url;

        return $this;
    }

    public function getDataType(): string
    {
        return 'domain';
    }

    /**
     * @return Collection
     */
    public function getTopicTrustFlows(): Collection
    {
        return $this->topicTrustFlows;
    }

    public function addTopicTrustFlow(TopicTrustFlow $topicTrustFlow): self
    {
        if (!$this->topicTrustFlows->contains($topicTrustFlow)) {
            $this->topicTrustFlows[] = $topicTrustFlow;
            $topicTrustFlow->setDomain($this);
        }

        return $this;
    }

    public function removeTopicTrustFlow(TopicTrustFlow $topicTrustFlow): self
    {
        if ($this->topicTrustFlows->contains($topicTrustFlow)) {
            $this->topicTrustFlows->removeElement($topicTrustFlow);
            // set the owning side to null (unless already changed)
            if ($topicTrustFlow->getDomain() === $this) {
                $topicTrustFlow->setDomain(null);
            }
        }

        return $this;
    }

    public function resetTopicTrustFlows(): self
    {
        foreach ($this->topicTrustFlows as $topicTrustFlow) {
            $this->topicTrustFlows->removeElement($topicTrustFlow);
            if ($topicTrustFlow->getDomain() === $this) {
                $topicTrustFlow->setDomain(null);
            }
        }

        $this->topicTrustFlows = new ArrayCollection();

        return $this;
    }
}
