<?php

/**
 * Custom extension for Isotope for Contao
 *
 * Copyright (c) 2014 Benjamin Roth [http://www.esales-media.de]
 *
 * @package eSM_isotope_custom
 * @link    http://www.esales-media.de
 * @license commercial
 */

namespace eSM_isotope_custom;

use Isotope\Interfaces\IsotopePrice;
use Isotope\Interfaces\IsotopeProductCollection;
use Isotope\Model\ProductCollection\Order;
use eSM_isotope_custom\Model\AffentalerRule as Rule;
use Isotope\Isotope;
use Isotope\Model\ProductCollection\Cart;
//use Isotope\Module\Cart;
use eSM_isotope_custom\Model\ProductCollectionSurcharge\AffentalerRule as RuleSurcharge;


class IsotopeHooks extends \Controller
{
    public function addProductToCollection($objProduct, $intQuantity, $ProductCollection)
    {
        if ($objProduct->not_buyable)
        {
          return 0;
        }
        return $intQuantity;
    }

  /**
   * Calculate the price for a product, applying rules and coupons
   *
   * @param    float
   * @param    object
   * @param    string
   * @param    int
   * @return float
   */
  public function calculatePrice($fltPrice, $objSource, $strField, $intTaxClass)
  {
    // RRP
    if ($strField === 'original_price' && ($objProduct = $objSource->getRelated('pid')) !== null)
    {
      if ($objProduct->price_rrp > $fltPrice)
      {
        return $objProduct->price_rrp;
      }
    }

    if ($objSource instanceof IsotopePrice && ('price' === $strField || 'low_price' === $strField || 'net_price' === $strField || 'gross_price' === $strField)) {

      // @todo try not to use getRelated() because it loads variants
      $objRules = Rule::findByProduct($objSource->getRelated('pid'), $strField, $fltPrice);

      if (null !== $objRules) {
        while ($objRules->next()) {
          // Check cart quantity
          if ($objRules->minItemQuantity > 0 || $objRules->maxItemQuantity >= 0) {
            if ('cart_products' === $objRules->quantityMode) {
              $intTotal = Isotope::getCart()->countItems();
            } elseif ('cart_items' === $objRules->quantityMode) {
              $intTotal = Isotope::getCart()->sumItemsQuantity();
            } else {
              $objItem = Isotope::getCart()->getItemForProduct($objSource->getRelated('pid'));
              $intTotal = (null === $objItem) ? 0 : $objItem->quantity;
            }

            if (($objRules->minItemQuantity > 0 && $objRules->minItemQuantity > $intTotal) || $objRules->maxItemQuantity < $intTotal) {
              continue;
            }
          }

          // We're unable to apply variant price rules to low_price (see #3189)
          if ('low_price' === $strField && 'variants' === $objRules->productRestrictions) {
            continue;
          }

          if ($objRules->current()->isPercentage()) {
            $fltDiscount = 100 + $objRules->current()->getPercentage();
            $fltDiscount = round($fltPrice - ($fltPrice / 100 * $fltDiscount), 10);

            $precision = Isotope::getConfig()->priceRoundPrecision;
            $factor    = pow(10, 2);
            $up        = $fltDiscount > 0 ? 'ceil' : 'floor';
            $down      = $fltDiscount > 0 ? 'floor' : 'ceil';

            switch ($objRules->rounding) {
              case Rule::ROUND_NORMAL:
                $fltDiscount = round($fltDiscount, $precision);
                break;

              case Rule::ROUND_UP:
                $fltDiscount = $up($fltDiscount * $factor) / $factor;
                break;

              case Rule::ROUND_DOWN:
              default:
                $fltDiscount = $down($fltDiscount * $factor) / $factor;
                break;
            }

            $fltPrice = $fltPrice - $fltDiscount;
          } else {
            $fltPrice = $fltPrice + $objRules->discount;
          }
        }
      }
    }

    return $fltPrice;
  }

  /**
   * Pattern for bulk image file import
   *
   * @param $arrPattern
   * @param $objProducts
   * @return array
   */
  public function addAssetImportRegexp($arrPattern, $objProducts)
  {
    $arrPattern[] = $objProducts->sku ? '[0]*'.$objProducts->sku : null;

    return $arrPattern;
  }

  public function modifyAddressFields($arrFields, $objAddress, $objStep)
  {
    foreach ($arrFields as $fieldName=>$field)
    {
      if ($fieldName == 'dateOfBirth')
      {
        $arrFields[$fieldName]['dca']['eval']['rgxp'] = 'date_age16';
      }
    }
    return $arrFields;
  }

  public function addCustomRegexp($strRegexp, &$varInput, \Widget $objWidget)
  {
    switch ($strRegexp)
    {
      case 'date_age16':
        if (!\Validator::isDate($varInput))
        {
          $objWidget->addError(sprintf($GLOBALS['TL_LANG']['ERR']['date'], \Date::getInputFormat(\Date::getNumericDateFormat())));
          return true;
        }
        else
        {
          // Validate the date (see #5086)
          try
          {
            new \Date($varInput, \Date::getNumericDateFormat());
          }
          catch (\OutOfBoundsException $e)
          {
            $objWidget->addError(sprintf($GLOBALS['TL_LANG']['ERR']['invalidDate'], $varInput));
          }

          // Age >= 16
          $Date = new \Date($varInput, \Date::getNumericDateFormat());
          $MinDate = new \Date(mktime(0,0,0,idate('m'),idate('d'),(idate('Y')-16)));

          if ($Date->tstamp > $MinDate->tstamp)
          {
            $objWidget->addError($GLOBALS['TL_LANG']['ERR']['date_age16']);
            return true;
          }

        }
        break;
    }

    return false;
  }

  public function getAttributesFromDca($arrAttributes, $objDca)
  {
    // modify $arrAttributes as needed
    // Convert timestamps
    if ($arrAttributes['value'] != '' && in_array($arrAttributes['rgxp'], array('date_age16')))
    {
      $objDate = new \Date($arrAttributes['value'], \Date::getFormatFromRgxp('date'));
      $arrAttributes['value'] = $objDate->date;
    }

    return $arrAttributes;
  }

  /**
   * Add cart rules to surcharges
   */
  public function findSurcharges(IsotopeProductCollection $objCollection)
  {
    $objCart = $objCollection;

    // The checkout review pages shows an order, but we need the cart
    // Only the cart contains coupons etc.
    if ($objCollection instanceof Order) {
      $objCart = $objCollection->getRelated('source_collection_id');
    }

    // Rules should only be applied to Cart, not any other product collection
    if (!($objCart instanceof Cart)) {
      return array();
    }

    $arrSurcharges = array();
    $objRules = Rule::findForCart();

    if (null !== $objRules) {
      while ($objRules->next()) {
        $objSurcharge = RuleSurcharge::createForRuleInCollection($objRules->current(), $objCollection);

        if (null !== $objSurcharge) {
          $arrSurcharges[] = $objSurcharge;
        }
      }
    }

    return $arrSurcharges;
  }

}