<?php

namespace AppBundle\Entity;

use Doctrine\ORM\Mapping as ORM;

/**
 * TravelPeriodPrice
 *
 * @ORM\Table(name="travel_period_price", uniqueConstraints={@ORM\UniqueConstraint(name="UK_price_type_period_id", columns={"price_type", "period_id"})}, indexes={@ORM\Index(name="FK_travel_period_price_travel_period", columns={"period_id"})})
 * @ORM\Entity
 */
class TravelPeriodPrice
{

    /**
     * @var float
     *
     * @ORM\Column(name="price_children", type="float", precision=10, scale=2, nullable=true)
     */
    private $priceChildren;

    /**
     * @var float
     *
     * @ORM\Column(name="price_net", type="float", precision=10, scale=2, nullable=false)
     */
    private $price = '0.00';

    /**
     * @var float
     *
     * @ORM\Column(name="price_comfort_net", type="float", precision=10, scale=2, nullable=false)
     */
    private $priceComfort = '0.00';

    /**
     * @var integer
     *
     * @ORM\Column(name="id", type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="IDENTITY")
     */
    private $id;

    /**
     * @var \AppBundle\Entity\TravelPeriod
     *
     * @ORM\ManyToOne(targetEntity="AppBundle\Entity\TravelPeriod", inversedBy="prices")
     * @ORM\JoinColumns({
     *   @ORM\JoinColumn(name="period_id", referencedColumnName="id")
     * })
     */
    private $period;

    /**
     * @ORM\ManyToOne(targetEntity="AppBundle\Entity\TravelPeriodPriceType")
     * @ORM\JoinColumns({
     *   @ORM\JoinColumn(name="price_type", referencedColumnName="id")
     * })
     */
    private $priceType;

    /**
     * @ORM\Column(type="integer", nullable=false, name="price_type")
     */
    private $priceTypeId;

    private $effectivePrice = null;
    private $effectiveChildPrice = null;
    private $effectiveComfortPrice = null;

    /**
     * Set priceType
     *
     * @param integer $priceType
     *
     * @return TravelPeriodPrice
     */
    public function setPriceType($priceType)
    {
        $this->priceType = $priceType;

        return $this;
    }

    /**
     * Get priceType
     *
     * @return integer
     */
    public function getPriceType()
    {
        return $this->priceType;
    }

    /**
     * Set priceChildren
     *
     * @param float $priceChildren
     *
     * @return TravelPeriodPrice
     */
    public function setPriceChildren($priceChildren)
    {
        $this->priceChildren = $priceChildren;

        return $this;
    }

    /**
     * Get priceChildren
     *
     * @return float
     */
    public function getPriceChildren()
    {
        return $this->priceChildren;
    }

    /**
     * Set price
     *
     * @param float $price
     *
     * @return TravelPeriodPrice
     */
    public function setPrice($price)
    {
        $this->price = $price;

        return $this;
    }

    /**
     * Get price
     *
     * @return float
     */
    public function getPrice()
    {
        return $this->price;
    }

    /**
     * Set priceComfort
     *
     * @param float $priceComfort
     *
     * @return TravelPeriodPrice
     */
    public function setPriceComfort($priceComfort)
    {
        $this->priceComfort = $priceComfort;

        return $this;
    }

    /**
     * Get priceComfort
     *
     * @return float
     */
    public function getPriceComfort()
    {
        return $this->priceComfort;
    }

    /**
     * Get id
     *
     * @return integer
     */
    public function getId()
    {
        return $this->id;
    }

    /**
     * Set period
     *
     * @param \AppBundle\Entity\TravelPeriod $period
     *
     * @return TravelPeriodPrice
     */
    public function setPeriod(\AppBundle\Entity\TravelPeriod $period = null)
    {
        $this->period = $period;

        return $this;
    }

    /**
     * Get period
     *
     * @return \AppBundle\Entity\TravelPeriod
     */
    public function getPeriod()
    {
        return $this->period;
    }

    /**
     * Set priceTypeId
     *
     * @param integer $priceTypeId
     *
     * @return TravelPeriodPrice
     */
    public function setPriceTypeId($priceTypeId)
    {
        $this->priceTypeId = $priceTypeId;

        return $this;
    }

    /**
     * Get priceTypeId
     *
     * @return integer
     */
    public function getPriceTypeId()
    {
        return $this->priceTypeId;
    }

    /**
     * @return float
     * @throws \Exception
     */
    public function getEffectivePrice()
    {
        if ($this->effectivePrice === null)
        {
            throw new \Exception('Effective price must be set from outside before reading it.');
        }
        return $this->effectivePrice;
    }

    /**
     * @param float $effectivePrice
     */
    public function setEffectivePrice($effectivePrice)
    {
        $this->effectivePrice = $effectivePrice;
    }

    /**
     * Probably getEffectiveDiscountPrice() is the method you are actually looking for.
     * @return float|null
     */
    public function getDiscountPrice()
    {
        return $this->calculateDiscountPrice($this->price);
    }

    /**
     * @return float
     * @throws \Exception
     */
    public function getEffectiveDiscountPrice()
    {
        if ($this->effectivePrice === null)
        {
            throw new \Exception('Effective price must be set from outside before reading effective discount price.');
        }
        return $this->calculateDiscountPrice($this->effectivePrice);
    }

    /**
     * @return float
     * @throws \Exception
     *
     * @todo The child price will not be set yet. This is just a preparation for later
     */
    public function getEffectiveChildPrice()
    {
        if ($this->effectiveChildPrice === null)
        {
            throw new \Exception('Effective child price must be set from outside before reading it.');
        }
        return $this->effectiveChildPrice;
    }

    /**
     * @param null $effectiveChildPrice
     */
    public function setEffectiveChildPrice($effectiveChildPrice)
    {
        $this->effectiveChildPrice = $effectiveChildPrice;
    }

    /**
     * @return float|null
     * @throws \Exception
     */
    public function getEffectiveComfortPrice()
    {
        if ($this->effectiveComfortPrice === null)
        {
            throw new \Exception('Effective comfort price must be set from outside before reading it.');
        }
        return $this->effectiveComfortPrice;
    }

    /**
     * @param float|null $effectiveComfortPrice
     */
    public function setEffectiveComfortPrice($effectiveComfortPrice)
    {
        $this->effectiveComfortPrice = $effectiveComfortPrice;
    }

    private function calculateDiscountPrice($price)
    {
        if ($this->getPeriod() == null)
        {
            return null;
        }
        $newPrice = $price;
        foreach ($this->getPeriod()->getDiscounts() as $discount)
        {
            $newPrice -= $discount->getPercent()
              ? round($newPrice * $discount->getValue() / 100, 2) // #TODO FIXME
              : $discount->getValue();
        }
        $program = $this->getPeriod()->getProgram();
        if ($program != null && $program->getDiscount() != null)
        {
            $newPrice -= $program->getDiscountIsPercentValue()
              ? round($price * $program->getDiscount() / 100, 2) // #TODO FIXME
              : $program->getDiscount();
        }
        return $price == $newPrice ? null : $newPrice;
    }
}
