<?php
/**
* @version	$Id: shipping_costs_event_handler.php 16516 2017-01-20 14:12:22Z alex $
* @package	In-Commerce
* @copyright	Copyright (C) 1997 - 2009 Intechnic. All rights reserved.
* @license	Commercial License
* This software is protected by copyright law and international treaties.
* Unauthorized reproduction or unlicensed usage of the code of this program,
* or any portion of it may result in severe civil and criminal penalties,
* and will be prosecuted to the maximum extent possible under the law
* See http://www.in-portal.org/commercial-license for copyright notices and details.
*/

defined('FULL_PATH') or die('restricted access!');

class ShippingCostsEventHandler extends kDBEventHandler {

	/**
	 * Allows to override standard permission mapping
	 *
	 * @return void
	 * @access protected
	 * @see kEventHandler::$permMapping
	 */
	protected function mapPermissions()
	{
		parent::mapPermissions();

		$permissions = Array(
			'OnPropagate'	=>	Array('subitem' => 'add|edit'),
			'OnClearAll'	=>	Array('subitem' => 'add|edit'),
			'OnSaveCreated'	=>	Array('subitem' => 'add|edit'),
		);

		$this->permMapping = array_merge($this->permMapping, $permissions);
	}

	/**
	 * Creates new kDBItem
	 *
	 * @param kEvent $event
	 * @return void
	 * @access protected
	 */
	protected function OnCreate(kEvent $event)
	{
		/** @var kDBItem $object */
		$object = $event->getObject(Array ('skip_autoload' => true));

		$zones_object = $this->Application->recallObject('z');

		$sql = 'SELECT ZoneID
				FROM ' . $zones_object->TableName . '
				WHERE ShippingTypeID = ' . $this->Application->GetVar('s_id');
		$res = $this->Conn->GetCol($sql);

		$sql = 'DELETE FROM ' . $object->TableName . '
				WHERE ZoneID IN (' . implode(',', $res) . ')';
		$this->Conn->Query($sql);

		// creates multiple db records from single request (OnCreate event only creates 1 record)
		$items_info = $this->Application->GetVar($event->getPrefixSpecial(true));

		if ( !$items_info ) {
			return;
		}

		foreach ($items_info as $field_values) {
			$object->setID(0);
			$object->SetFieldsFromHash($field_values);
			$event->setEventParam('form_data', $field_values);
			$this->customProcessing($event, 'before');

			if ( $object->Create() ) {
				$this->customProcessing($event, 'after');
				$event->status = kEvent::erSUCCESS;
			}
			else {
				$event->status = kEvent::erFAIL;
				$event->redirect = false;
				$this->Application->SetVar($event->getPrefixSpecial() . '_SaveEvent', 'OnCreate');
				$object->setID(0);
			}
		}
	}

	/**
	 * Enter description here...
	 *
	 * @param kEvent $event
	 */
	function OnPropagate($event)
	{
	//	$this->OnCreate($event);

		$object = $event->getObject();

		$shipping_object = $this->Application->recallObject('s');

		if( $this->Application->GetVar('br_propagate_id') )
		{
			$propagate_id = $this->Application->GetVar('br_propagate_id');
			$idfield = 'BracketId';
		}
		else
		{
			$propagate_id = $this->Application->GetVar('z_propagate_id');
			$idfield = 'ZoneID';
		}

		$cost_type = $shipping_object->GetDBField('CostType');
		switch($cost_type)
		{
			case 1:
				$affected_fields = Array(0 => 'Flat');
				break;
			case 2:
				$affected_fields = Array(0 => 'PerUnit');
				break;
			default:
				$affected_fields = Array(0 => 'PerUnit', 1 => 'Flat');
				break;
		}

		$sql = 'SELECT ShippingCostId,'.implode(',', $affected_fields).'
				FROM '.$object->TableName.'
				WHERE '.$idfield.'='.$propagate_id;
		$res = $this->Conn->Query($sql);

		if(is_array($res))
		{
			$res = array_reverse($res);
			foreach($affected_fields as $field)
			{
				$first_elem = getArrayValue($res, 0);
				if( (double)$first_elem[$field] )
				{
					$iterating_value = $first_elem[$field];
					$second_elem = getArrayValue($res, 1);
					if( is_array($second_elem) && (double)$second_elem[$field] )
					{
						$increment = $second_elem[$field] - $first_elem[$field];
					}
					else
					{
						$increment = 0;
					}

					foreach($res as $record)
					{
						$object->Load($record['ShippingCostId']);

						$new_value = ($iterating_value >= 0) ? $iterating_value : null;
						$object->SetDBField($field, $new_value);

						$object->Update();
						$iterating_value += $increment;
					}
				}
			}
		}

		/*$shipping_event = new kEvent('s:OnPreSave');
		$shipping_event->status = kEvent::erFATAL;
		$this->Application->HandleEvent($shipping_event);*/
	}

	/**
	 * Enter description here...
	 *
	 * @param kEvent $event
	 */
	function OnClearAll($event)
	{
		/** @var kDBItem $object */
		$object = $event->getObject(Array ('skip_autoload' => true));

		/** @var kDBItem $zones_object */
		$zones_object = $this->Application->recallObject('z');

		$sql = 'SELECT ZoneID
				FROM ' . $zones_object->TableName . '
				WHERE ShippingTypeID = ' . $this->Application->GetVar('s_id');
		$res = $this->Conn->GetCol($sql);

		$sql = 'DELETE FROM ' . $object->TableName . '
				WHERE ZoneID IN (' . implode(',', $res) . ')';
		$this->Conn->Query($sql);

		$event->setRedirectParams(Array ('opener' => 's', 'pass_events' => false));
		$event->status = kEvent::erSUCCESS;
	}

	/**
	 * Apply custom processing to item
	 *
	 * @param kEvent $event
	 * @param string $type
	 * @return void
	 * @access protected
	 */
	protected function customProcessing(kEvent $event, $type)
	{
		if ( $type == 'before' && $this->Application->GetVar('sc') ) {
			/** @var kDBItem $shipping_obj */
			$shipping_obj = $this->Application->recallObject('s');

			/** @var kDBItem $object */
			$object = $event->getObject();

			$zero_if_empty = $shipping_obj->GetDBField('ZeroIfEmpty');

			if ( $object->GetDBField('Flat') == '' ) {
				$flat = $zero_if_empty ? 0 : null;
				$object->SetDBField('Flat', $flat);
			}
			if ( $object->GetDBField('PerUnit') == '' ) {
				$per_unit = $zero_if_empty ? 0 : null;
				$object->SetDBField('PerUnit', $per_unit);
			}
		}
	}

	/**
	 * Enter description here...
	 *
	 * @param kEvent $event
	 */
	function OnSaveCreated($event)
	{
		$event->CallSubEvent('OnCreate');
		$event->redirect = false;
		$event->setRedirectParams(Array ('opener' => 's', 'pass' => 'all'));
	}

	/**
	 * Occurs after an item has been copied to temp
	 * Id of copied item is passed as event' 'id' param
	 *
	 * @param kEvent $event
	 * @return void
	 * @access protected
	 */
	protected function OnAfterCopyToTemp(kEvent $event)
	{
		parent::OnAfterCopyToTemp($event);

		$id = $event->getEventParam('id');

		/** @var kDBItem $object */
		$object = $this->Application->recallObject($event->Prefix . '.-item', $event->Prefix);

		$object->SwitchToTemp();
		$object->Load($id);

		/** @var kDBItem $shipping_obj */
		$shipping_obj = $this->Application->recallObject('s');

		/** @var LanguagesItem $lang_object */
		$lang_object = $this->Application->recallObject('lang.current');

		// by weight and US/UK system - we need to store recalculated price per Kg cause shipping calculation is done per Kg!
		if ( $shipping_obj->GetDBField('Type') == 1 && $lang_object->GetDBField('UnitSystem') == 2 ) {
			$object->SetDBField('PerUnit', $object->GetDBField('PerUnit') * kUtil::POUND_TO_KG);
			$object->Update(null, null, true);
		}
	}

	/**
	 * Occurs before an item is copied to live table (after all foreign keys have been updated)
	 * Id of item being copied is passed as event' 'id' param
	 *
	 * @param kEvent $event
	 * @return void
	 * @access protected
	 */
	protected function OnBeforeCopyToLive(kEvent $event)
	{
		parent::OnBeforeCopyToLive($event);

		$id = $event->getEventParam('id');

		/** @var kDBItem $object */
		$object = $this->Application->recallObject($event->Prefix . '.-item', $event->Prefix);

		$object->SwitchToTemp();
		$object->Load($id);

		/** @var kDBItem $shipping_obj */
		$shipping_obj = $this->Application->recallObject('s');

		/** @var LanguagesItem $lang_object */
		$lang_object = $this->Application->recallObject('lang.current');

		// by weight and US/UK system - we need to store recalculated price per Kg cause shipping calculation is done per Kg!
		if ( $shipping_obj->GetDBField('Type') == 1 && $lang_object->GetDBField('UnitSystem') == 2 ) {
			$object->SetDBField('PerUnit', $object->GetDBField('PerUnit') / kUtil::POUND_TO_KG);
			$object->Update(null, null, true);
		}
	}
}
