<?php

namespace App\Entity;

use App\Entity\Content\Placement;
use App\Entity\Content\Status;
use App\Entity\Content\Type;
use App\Entity\Traits\TimestampableTrait;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM;
use Doctrine\ORM\Mapping\Index;
use Doctrine\ORM\Mapping\Table;
use Symfony\Component\Validator\Constraints as Assert;

/**
 * @ORM\Entity()
 * @Table(indexes={@Index(columns={"title"}, flags={"fulltext"})})
 * @ORM\EntityListeners({"App\EntityListener\ContentListener"})
 */
class Content implements BroadcastableInterface
{
    use TimestampableTrait;

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

    /**
     * @ORM\Column(type="string", length=255)
     */
    private $title;

    /**
     * @ORM\ManyToOne(targetEntity="App\Entity\Campaign", inversedBy="contents")
     * @ORM\JoinColumn(onDelete="CASCADE")
     */
    private $campaign;

    /**
     * @ORM\ManyToOne(targetEntity="App\Entity\User")
     * @ORM\JoinColumn(nullable=true, onDelete="SET NULL")
     */
    private $user;

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

    /**
     * @ORM\ManyToOne(targetEntity="App\Entity\Content\Status", inversedBy="contents")
     * @ORM\JoinColumn(nullable=true)
     */
    private $status;

    /**
     * @ORM\OneToMany(targetEntity="App\Entity\ContentVersion", mappedBy="content")
     * @ORM\OrderBy({"createdAt" = "DESC"})
     */
    private $versions;

    /**
     * @ORM\OneToMany(targetEntity="App\Entity\Negotiation", mappedBy="content")
     */
    private $negotiations;

    /**
     * @ORM\OneToMany(targetEntity="App\Entity\Link", mappedBy="content")
     */
    private $links;

    /**
     * @ORM\OneToMany(targetEntity="App\Entity\CommentContent", mappedBy="content")
     */
    private $comments;

    /**
     * @ORM\OneToMany(targetEntity="App\Entity\EventLogContent", mappedBy="content")
     */
    private $eventLogs;

    /**
     * @ORM\Column(type="integer", options={"default": 700}, nullable=false)
     */
    private $desiredWordCount = 700;

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

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

    /**
     * @ORM\OneToMany(targetEntity="App\Entity\FileAssociationContent", mappedBy="content")
     */
    private $files;

    /**
     * @ORM\Column(type="integer", options={"default": 0}, nullable=false)
     */
    private $wordCount = 0;

    /**
     * @ORM\Column(type="smallint", options={"default": 0}, nullable=true)
     */
    private $priority;

    /**
     * @ORM\ManyToOne(targetEntity="App\Entity\Content\Type")
     * @ORM\JoinColumn(nullable=false)
     * @Assert\NotBlank()
     */
    private $type;

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

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

    /**
     * @ORM\ManyToOne(targetEntity="App\Entity\Content\Placement")
     * @ORM\JoinColumn(nullable=true)
     */
    private $placement;

    /**
     * @ORM\OneToOne(targetEntity="App\Entity\CopyscapeReport", mappedBy="content")
     */
    private $copyscapeReport;

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

    public function __construct()
    {
        $this->versions = new ArrayCollection();
        $this->negotiations = new ArrayCollection();
        $this->links = new ArrayCollection();
        $this->comments = new ArrayCollection();
        $this->eventLogs = new ArrayCollection();
    }

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

    public function getTitle(): ?string
    {
        return $this->title;
    }

    public function setTitle(string $title): self
    {
        $this->title = $title;

        return $this;
    }

    public function getCampaign(): ?Campaign
    {
        return $this->campaign;
    }

    public function setCampaign(?Campaign $campaign): self
    {
        $this->campaign = $campaign;

        return $this;
    }

    public function getUser(): ?User
    {
        return $this->user;
    }

    public function setUser(?User $user): self
    {
        $this->user = $user;

        return $this;
    }

    public function getDueDate(): ?string
    {
        return $this->dueDate;
    }

    public function setDueDate(?string $dueDate): self
    {
        $this->dueDate = $dueDate;

        return $this;
    }

    public function getStatus(): ?Status
    {
        return $this->status;
    }

    public function setStatus(?Status $status): self
    {
        $this->status = $status;

        return $this;
    }

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

    public function addVersion(ContentVersion $version): self
    {
        if (!$this->versions->contains($version)) {
            $this->versions[] = $version;
            $version->setContent($this);
        }

        return $this;
    }

    public function removeVersion(ContentVersion $version): self
    {
        if ($this->versions->contains($version)) {
            $this->versions->removeElement($version);
            // set the owning side to null (unless already changed)
            if ($version->getContent() === $this) {
                $version->setContent(null);
            }
        }

        return $this;
    }

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

    public function addNegotiation(Negotiation $negotiation): self
    {
        if (!$this->negotiations->contains($negotiation)) {
            $this->negotiations[] = $negotiation;
            $negotiation->setContent($this);
        }

        return $this;
    }

    public function removeNegotiation(Negotiation $negotiation): self
    {
        if ($this->negotiations->contains($negotiation)) {
            $this->negotiations->removeElement($negotiation);
            // set the owning side to null (unless already changed)
            if ($negotiation->getContent() === $this) {
                $negotiation->setContent(null);
            }
        }

        return $this;
    }

    public function getDesiredWordCount(): ?int
    {
        return $this->desiredWordCount;
    }

    public function setDesiredWordCount(?int $desiredWordCount): self
    {
        $this->desiredWordCount = $desiredWordCount;

        return $this;
    }

    public function getAnchorHref(): ?string
    {
        return $this->anchorHref;
    }

    public function setAnchorHref(?string $anchorHref): self
    {
        $this->anchorHref = $anchorHref;

        return $this;
    }

    public function getAnchorText(): ?string
    {
        return $this->anchorText;
    }

    public function setAnchorText(?string $anchorText): self
    {
        $this->anchorText = $anchorText;

        return $this;
    }

    /**
     * @return FileAssociationContent[]|null
     */
    public function getFiles()
    {
        return $this->files;
    }

//    /**
//     * @return Collection|Link[]
//     */
//    public function getLinks(): Collection
//    {
//        return $this->links;
//    }
//
//    public function addLink(Link $link): self
//    {
//        if (!$this->links->contains($link)) {
//            $this->links[] = $link;
//            $link->setContent($this);
//        }
//
//        return $this;
//    }
//
//    public function removeLink(Link $link): self
//    {
//        if ($this->links->contains($link)) {
//            $this->links->removeElement($link);
//            // set the owning side to null (unless already changed)
//            if ($link->getContent() === $this) {
//                $link->setContent(null);
//            }
//        }
//
//        return $this;
//    }

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

    public function getWordCount(): ?int
    {
        return $this->wordCount;
    }

    public function setWordCount(int $wordCount): self
    {
        $this->wordCount = $wordCount;

        return $this;
    }

    public function getPriority(): ?int
    {
        return $this->priority;
    }

    public function setPriority(int $priority): self
    {
        $this->priority = $priority;

        return $this;
    }

    public function getType(): ?Type
    {
        return $this->type;
    }

    public function setType(?Type $type): self
    {
        $this->type = $type;

        return $this;
    }

    public function getMetaDescription(): ?string
    {
        return $this->metaDescription;
    }

    public function setMetaDescription(?string $metaDescription): self
    {
        $this->metaDescription = $metaDescription;

        return $this;
    }

    public function getMetaTitle(): ?string
    {
        return $this->metaTitle;
    }

    public function setMetaTitle(?string $metaTitle): self
    {
        $this->metaTitle = $metaTitle;

        return $this;
    }

    public function getPlacement(): ?Placement
    {
        return $this->placement;
    }

    public function setPlacement(?Placement $placement): self
    {
        $this->placement = $placement;

        return $this;
    }

    public function getCopyscapeResult(): ?bool
    {
        if (!$this->getCopyscapeReport()) {
            return null;
        } else {
            return (bool)$this->getCopyscapeReport()->getMatched();
        }
    }

    public function getCopyscapeReport(): ?CopyscapeReport
    {
        return $this->copyscapeReport;
    }

    public function setCopyscapeReport(CopyscapeReport $copyscapeReport): self
    {
        $this->copyscapeReport = $copyscapeReport;

        // set the owning side of the relation if necessary
        if ($this !== $copyscapeReport->getContent()) {
            $copyscapeReport->setContent($this);
        }

        return $this;
    }

    /**
     * @return string
     */
    public function getBrief(): ?string
    {
        return $this->brief;
    }

    /**
     * @param string $brief
     */
    public function setBrief(string $brief): void
    {
        $this->brief = $brief;
    }
}
