<?php
/*
* 2007-2015 PrestaShop
*
* NOTICE OF LICENSE
*
* This source file is subject to the Open Software License (OSL 3.0)
* that is bundled with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://opensource.org/licenses/osl-3.0.php
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@prestashop.com so we can send you a copy immediately.
*
* DISCLAIMER
*
* Do not edit or add to this file if you wish to upgrade PrestaShop to newer
* versions in the future. If you wish to customize PrestaShop for your
* needs please refer to http://www.prestashop.com for more information.
*
*  @author PrestaShop SA <contact@prestashop.com>
*  @copyright  2007-2015 PrestaShop SA
*  @license    http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
*  International Registered Trademark & Property of PrestaShop SA
*/

/**
 * @since 1.5.0
 *
 * TaxCaculator is responsible of the tax computation
 */
class TaxCalculatorCore
{
	/**
  	 * COMBINE_METHOD sum taxes
	 * eg: 100€ * (10% + 15%)
	 */
	const COMBINE_METHOD = 1;

	/**
	 * ONE_AFTER_ANOTHER_METHOD apply taxes one after another
	 * eg: (100€ * 10%) * 15%
	 */
	const ONE_AFTER_ANOTHER_METHOD = 2;

	/**
	 * @var array $taxes
	 */
	public $taxes;

	/**
	 * @var int $computation_method (COMBINE_METHOD | ONE_AFTER_ANOTHER_METHOD)
	 */
	public $computation_method;


	/**
	 * @param array $taxes
	 * @param int $computation_method (COMBINE_METHOD | ONE_AFTER_ANOTHER_METHOD)
	 */
	public function __construct(array $taxes = array(), $computation_method = TaxCalculator::COMBINE_METHOD)
	{
		// sanity check
		foreach ($taxes as $tax)
			if (!($tax instanceof Tax))
				throw new Exception('Invalid Tax Object');

		$this->taxes = $taxes;
		$this->computation_method = (int)$computation_method;
	}

	/**
	 * Compute and add the taxes to the specified price
	 *
	 * @param float $price_te price tax excluded
	 * @return float price with taxes
	 */
	public function addTaxes($price_te)
	{
		return $price_te * (1 + ($this->getTotalRate() / 100));
	}


	/**
	 * Compute and remove the taxes to the specified price
	 *
	 * @param float $price_ti price tax inclusive
	 * @return float price without taxes
	 */
	public function removeTaxes($price_ti)
	{
		return $price_ti / (1 + $this->getTotalRate() / 100);
	}

	/**
	 * @return float total taxes rate
	 */
	public function getTotalRate()
	{
		$taxes = 0;
		if ($this->computation_method == TaxCalculator::ONE_AFTER_ANOTHER_METHOD)
		{
			$taxes = 1;
			foreach ($this->taxes as $tax)
				$taxes *= (1 + (abs($tax->rate) / 100));

			$taxes = $taxes - 1;
			$taxes = $taxes * 100;
		}
		else
		{
			foreach ($this->taxes as $tax)
				$taxes += abs($tax->rate);
		}

		return (float)$taxes;
	}

	public function getTaxesName()
	{
		$name = '';
		foreach ($this->taxes as $tax)
			$name .= $tax->name[(int)Context::getContext()->language->id].' - ';

		$name = rtrim($name, ' - ');

		return $name;
	}

	/**
	 * Return the tax amount associated to each taxes of the TaxCalculator
	 *
	 * @param float $price_te
	 * @return array $taxes_amount
	 */
	public function getTaxesAmount($price_te)
	{
		$taxes_amounts = array();

		foreach ($this->taxes as $tax)
		{
			if ($this->computation_method == TaxCalculator::ONE_AFTER_ANOTHER_METHOD)
			{
				$taxes_amounts[$tax->id] = $price_te * (abs($tax->rate) / 100);
				$price_te = $price_te + $taxes_amounts[$tax->id];
			}
			else
				$taxes_amounts[$tax->id] = ($price_te * (abs($tax->rate) / 100));
		}

		return $taxes_amounts;
	}

	/**
	 * Return the total taxes amount
	 *
	 * @param float $price_te
	 * @return float $amount
	 */
	public function getTaxesTotalAmount($price_te)
	{
		$amount = 0;

		$taxes = $this->getTaxesAmount($price_te);
		foreach ($taxes as $tax)
			$amount += $tax;

		return $amount;
	}
}
