<?php

namespace App\Entity;

use App\Entity\Prospect\Problem;
use App\Entity\Traits\ContactableTrait;
use App\Entity\Traits\TimestampableTrait;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Validator\Constraints as Assert;

/**
 * Class Prospect.
 *
 * @ORM\Entity
 */
class Prospect
{
    use ContactableTrait, TimestampableTrait;

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

    /**
     * @ORM\ManyToOne(targetEntity="App\Entity\Domain", inversedBy="prospects")
     * @Assert\NotBlank()
     */
    private $domain;

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

    /**
     * @ORM\ManyToMany(targetEntity="App\Entity\Category", inversedBy="prospects")
     * @ORM\JoinColumn(name="category_id", referencedColumnName="id")
     */
    private $categories;

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

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

    /**
     * @ORM\OneToMany(targetEntity="App\Entity\NegotiationMessage", mappedBy="prospect")
     */
    private $negotiationMessages;

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

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

    /**
     * @ORM\Column(type="integer", options={"default" : 50})
     */
    private $score = 50;

    /**
     * @ORM\OneToMany(targetEntity="App\Entity\Prospect\Problem", mappedBy="prospect", orphanRemoval=true)
     * @ORM\OrderBy({"createdAt" = "DESC"})
     */
    private $problems;

    /**
     * @ORM\ManyToMany(targetEntity="App\Entity\Research", mappedBy="prospects")
     */
    private $researches;

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

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

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

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

    /**
     * @ORM\ManyToOne(targetEntity="App\Entity\Currency")
     */
    private $currency;

    public function __construct()
    {
        $this->categories = new ArrayCollection();
        $this->negotiations = new ArrayCollection();
        $this->negotiationMessages = new ArrayCollection();
        $this->problems = new ArrayCollection();
        $this->researches = new ArrayCollection();
        $this->links = new ArrayCollection();
    }

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

    public function getDomain(): ?Domain
    {
        return $this->domain;
    }

    public function setDomain(Domain $domain): self
    {
        $this->domain = $domain;

        return $this;
    }

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

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

        return $this;
    }

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

    public function addCategory(Category $category): self
    {
        if (!$this->categories->contains($category)) {
            $this->categories[] = $category;
        }

        return $this;
    }

    public function removeCategory(Category $category): self
    {
        if ($this->categories->contains($category)) {
            $this->categories->removeElement($category);
        }

        return $this;
    }

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

    public function addNegotiationMessage(NegotiationMessage $negotiationMessage): self
    {
        if (!$this->negotiationMessages->contains($negotiationMessage)) {
            $this->negotiationMessages[] = $negotiationMessage;
            $negotiationMessage->setProspect($this);
        }

        return $this;
    }

    public function removeNegotiationMessage(NegotiationMessage $negotiationMessage): self
    {
        if ($this->negotiationMessages->contains($negotiationMessage)) {
            $this->negotiationMessages->removeElement($negotiationMessage);
            // set the owning side to null (unless already changed)
            if ($negotiationMessage->getProspect() === $this) {
                $negotiationMessage->setProspect(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->setProspect($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->getProspect() === $this) {
                $negotiation->setProspect(null);
            }
        }

        return $this;
    }

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

    public function getPaypalEmail(): ?string
    {
        return $this->paypalEmail;
    }

    public function setPaypalEmail(?string $paypalEmail): self
    {
        $this->paypalEmail = $paypalEmail;

        return $this;
    }

    public function getComment(): ?string
    {
        return $this->comment;
    }

    public function setComment(?string $comment): self
    {
        $this->comment = $comment;

        return $this;
    }

    public function getScore(): ?int
    {
        return $this->score;
    }

    public function setScore(int $score): self
    {
        $this->score = $score;

        return $this;
    }

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

    public function addProblem(Problem $problem): self
    {
        if (!$this->problems->contains($problem)) {
            $this->problems[] = $problem;
            $problem->setProspect($this);
        }

        return $this;
    }

    public function removeProblem(Problem $problem): self
    {
        if ($this->problems->contains($problem)) {
            $this->problems->removeElement($problem);
            // set the owning side to null (unless already changed)
            if ($problem->getProspect() === $this) {
                $problem->setProspect(null);
            }
        }

        return $this;
    }

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

    public function addResearch(Research $research): self
    {
        if (!$this->researches->contains($research)) {
            $this->researches[] = $research;
            $research->addProspect($this);
        }

        return $this;
    }

    public function removeResearch(Research $research): self
    {
        if ($this->researches->contains($research)) {
            $this->researches->removeElement($research);
            $research->removeProspect($this);
        }

        return $this;
    }

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

    public function setType(string $type): self
    {
        $this->type = ucfirst($type);

        return $this;
    }

    public function getGuidelines(): ?string
    {
        return $this->guidelines;
    }

    public function setGuidelines(?string $guidelines): self
    {
        $this->guidelines = $guidelines;

        return $this;
    }

    public function getContactPage(): ?string
    {
        return $this->contactPage;
    }

    public function setContactPage(string $contactPage): self
    {
        $this->contactPage = $contactPage;

        return $this;
    }

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

    public function setCountry(?Country $country): self
    {
        $this->country = $country;

        return $this;
    }

    public function getCurrency(): ?Currency
    {
        return $this->currency;
    }

    public function setCurrency(?Currency $currency): self
    {
        $this->currency = $currency;

        return $this;
    }

    public function getMostRecentAgreedPrice()
    {
        $prices = $this->getNegotiations()->filter(function (Negotiation $negotiation) {
            return
                null !== $negotiation->getCostAgreed();
        });
        if ($prices->count() > 0) {
            return $prices->last()->getCostAgreed();
        }

        return null;
    }

    public function getLinksCount(): int
    {
        return $this->getLinks()->count();
    }
}
