<?php

namespace App\Entity\Model;

use App\Util\Inflector;
use Doctrine\ORM\Mapping as ORM;
use Gedmo\Sluggable\Util\Urlizer;
use Symfony\Component\Validator\Constraints as Assert;

/**
 * App\Entity\Model\Item
 *
 * @ORM\Entity(repositoryClass="App\Repository\ItemRepository")
 * @ORM\Table(indexes={
 *    @ORM\Index(name="invoice_item_desc_idx", columns={"description"})
 * })
 */
class Item implements \JsonSerializable
{

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

    /**
     * @var decimal $quantity
     *
     * @ORM\Column(type="decimal", precision=20, scale=6)
     * @Assert\NotBlank()
     */
    private $quantity;

    /**
     * @var decimal $discount
     *
     * @ORM\Column(type="decimal", precision=15, scale=2)
     */
    private $discount;

    /**
     * @var string $description
     *
     * @ORM\Column()
     */
    private $description;

    /**
     * @var decimal $unitary_cost
     *
     * @ORM\Column(type="decimal", precision=20, scale=6)
     * @Assert\NotBlank()
     */
    private $unitary_cost;

    /**
     * @ORM\ManyToOne(targetEntity="App\Entity\Model\Tax")
     * @ORM\JoinColumn(name="tax_id", referencedColumnName="id", onDelete="SET NULL")
     *
     */
    private $taxes;

    /**
     * @ORM\ManyToOne(targetEntity="App\Entity\Model\Product", inversedBy="items")
     * @ORM\JoinColumn(name="product_id", referencedColumnName="id", onDelete="SET NULL")
     */
    private $product;

    /**
     * @ORM\ManyToMany(targetEntity="App\Entity\Model\Invoice", mappedBy="items")
     */
    private $invoice;

    /**
     * @var decimal $val_iva
     *
     * @ORM\Column(type="decimal", precision=15, scale=2)
     * @Assert\NotBlank()
     */
    private $valiva;

    /**
     * @var decimal
     *
     * @ORM\Column(type="decimal", precision=15, scale=2)
     * @Assert\NotBlank()
     */
    private $subtotal;

    /**
     * @var decimal $valdescuento
     *
     * @ORM\Column(type="decimal", precision=15, scale=2)
     * @Assert\NotBlank()
     */
    private $valdescuento;

    /**
     * @var decimal $neto
     *
     * @ORM\Column(type="decimal", precision=15, scale=2)
     * @Assert\NotBlank()
     */
    private $neto;

    /**
     * @var decimal $tasaimpuesto
     *
     * @ORM\Column(type="decimal", precision=15, scale=2)
     * @Assert\NotBlank()
     */
    private $tasaimpuesto;

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

    /**
     * Get quantity
     *
     * @return decimal
     */
    public function getQuantity()
    {
        return $this->quantity;
    }

    /**
     * Set Quantity
     *
     * @param decimal $quantity
     */
    public function setQuantity($quantity)
    {
        $this->quantity = $quantity;
    }

    /**
     * Get discount
     *
     * @return decimal
     */
    public function getDiscount()
    {
        return $this->discount;
    }

    /**
     * Set Discount
     *
     * @param decimal $discount
     */
    public function setDiscount($discount)
    {
        $this->discount = $discount;
    }

    /**
     * Get discount
     *
     * @return decimal
     */
    public function getDiscountPercent()
    {
        return $this->discount;
    }

    /**
     * Set Discount
     *
     * @param decimal $discount
     */
    public function setDiscountPercent($discount)
    {
        $this->discount = $discount;
    }

    /**
     * Get description
     *
     * @return string
     */
    public function getDescription()
    {
        return $this->description;
    }

    /**
     * Set description
     *
     * @param string $description
     */
    public function setDescription($description)
    {
        $this->description = strtoupper($description);
    }

    /**
     * Get unitary cost
     *
     * @return decimal
     */
    public function getUnitaryCost()
    {
        return $this->unitary_cost;
    }

    /**
     * Set unitary cost
     *
     * @param decimal $unitary_cost
     */
    public function setUnitaryCost($unitary_cost)
    {
        $this->unitary_cost = $unitary_cost;
    }

    /**
     * Get product
     *
     * @return \App\Entity\Model\Product
     */
    public function getProduct()
    {
        return $this->product;
    }

    /**
     * Set product
     *
     * @param \App\Entity\Model\Product $product
     */
    public function setProduct(Product $product)
    {
        $this->product = $product;
    }

    /** **************** CUSTOM METHODS ************* */

    /**
     * Get base amount
     *
     * @return float gross price of the item (times quantity)
     */
    public function getBaseAmount()
    {
        return $this->unitary_cost*$this->quantity;
    }

    /**
     * Get net amount
     *
     * @return float price with discount
     */
    public function getNetAmount()
    {
        return $this->getBaseAmount() - $this->getDiscountAmount();
    }

    /**
     * Get discount amount
     *
     * @return float amount to discount
     */
    public function getDiscountAmount()
    {
        $discount = $this->getDiscountPercent();
        return round($discount,2);
    }

    /**
     * Get tax amount
     *
     * @param array tax_names. if present, returns the amount for those taxes
     * @return float amount to tax
     */
    public function getTaxAmount($tax_names = array())
    {
        return $this->getNetAmount() * $this->getTaxesPercent($tax_names) / 100;
    }

    /**
     * Get gross amount
     *
     * @return float amount to pay after discount and taxes
     */
    public function getGrossAmount()
    {
        return $this->getNetAmount() + $this->getTaxAmount();
    }

    /**
     * Get taxes percent
     *
     * @param tax_names array if present shows only percent of those taxes
     * @return integer total percent of taxes to apply
     */
    public function getTaxesPercent($tax_names = array())
    {
        $tax_names = is_array($tax_names) ?
            array_map(array('Gedmo\Sluggable\Util\Urlizer', 'urlize'), $tax_names):
            array(Urlizer::urlize($tax_names)) ;
        $total = 0;
        //foreach ($this->getTaxes() as $tax) {
        if($this->taxes != null){
            $tax = $this->taxes;
            if (count($tax_names)==0 ||
                in_array(Urlizer::urlize(str_replace(' ', '', $tax->getName())), $tax_names)) {
                $total += $tax->getValue();
                $this->setTasaimpuesto($tax->getValue());
            }
        }
        return $total;
    }

    /**
     * Try to capture a "getTaxAmountTAXNAME" method.
     * This is to be able to use 'invoice.tax_amount_TAXNAME' in the templates
     *
     * @author JoeZ99 <jzarate@gmail.com>
     */
    public function __call($data, $argument)
    {
        if (strpos($data, 'getTaxAmount') === 0 && strlen($data)>12) {
            $tax_name = substr($data, 12);
            return $this->getTaxAmount($tax_name);
        }
        return false;
    }

    /**
     * Again, capture hipothetical {{invoice.base_amount}} and the like
     *
     */
    public function __get($name)
    {
        $method = Inflector::camelize("get_{$name}");
        if (method_exists($this, $method)) {
            return $this->$method();
        }
        return false;
    }

    /**
     * Twig template system needs this to answer true for the specified properties
     */
    public function __isset($name)
    {
        $classVars = array_keys(get_object_vars($this));
        $extraVars = ['discount_amount', 'base_amount', 'net_amount', 'tax_amount', 'gross_amount'];
        if (in_array($name, array_merge($classVars, $extraVars))) {
            return true;
        }

        return false;
    }

    public function __toString()
    {
        return (string) $this->description.': '.$this->quantity;
    }

    public function __construct()
    {
        //$this->taxes = new Tax();
        $this->quantity = 1;
        $this->discount = 0;
        $this->valdescuento = 0;
        $this->neto = 0;
    }

    /**
     * Add taxes
     *
     * @param App\Entity\Model\Tax $tax
     */
    public function setTaxes(Tax $tax)
    {
        $this->taxes = $tax;
    }


    /**
     * Get taxes
     *
     * @return Tax
     */
    public function getTaxes()
    {
        return $this->taxes;
    }

    /**
     *
     * Remove Tax
     *
     * @param App\Entity\Model\Tax
     */
    /*public function removeTax(\App\Entity\Model\Tax $tax)
    {
        $this->taxes->removeElement($tax);
    }
*/

    public function jsonSerialize()
    {
        return [
            'id' => $this->getId(),
            'unitary_cost' => $this->getUnitaryCost(),
            'description' => $this->getDescription(),
        ];
    }

    /**
     * @return decimal
     */
    public function getValiva()
    {
        return $this->valiva;
    }

    /**
     * @param decimal $valiva
     */
    public function setValiva($valiva)
    {
        $this->valiva = $valiva;
    }

    /**
     * @return decimal
     */
    public function getSubtotal()
    {
        return $this->subtotal;
    }

    /**
     * @param decimal $subtotal
     */
    public function setSubtotal($subtotal)
    {
        $this->subtotal = $subtotal;
    }

    /**
     * @return decimal
     */
    public function getValdescuento()
    {
        return $this->valdescuento;
    }

    /**
     * @param decimal $valdescuento
     */
    public function setValdescuento($valdescuento)
    {
        $this->valdescuento = $valdescuento;
    }

    /**
     * @return decimal
     */
    public function getNeto()
    {
        return $this->neto;
    }

    /**
     * @param decimal $neto
     */
    public function setNeto($neto)
    {
        $this->neto = $neto;
    }

    public function getTasaimpuesto()
    {
        return $this->tasaimpuesto;
    }

    public function setTasaimpuesto($tasaimpuesto)
    {
        $this->tasaimpuesto = $tasaimpuesto;
    }

}
