<?php
/**
* @version	$Id: shipping_tag_processor.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!');

// include globals.php from current folder
kUtil::includeOnce(MODULES_PATH . '/in-commerce/units/pricing/globals.php');

class ShippingTagProcessor extends kDBTagProcessor {

	function CostInputSize($params)
	{
		$object = $this->Application->recallObject( $this->getPrefixSpecial() );
		$prec_before_sep = $object->GetDBField('PrecisionBeforeSep');
		$prec_after_sep = $object->GetDBField('PrecisionAfterSep');
		return $prec_before_sep + $prec_after_sep + 1 + ($prec_before_sep > 3 ? 1:0);
	}

	function ShowCostsTable($params)
	{
		$object = $this->Application->recallObject( $this->getPrefixSpecial() );
		$zones_object = $this->Application->recallObject('z');
		$brackets_object = $this->Application->recallObject('br');

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

		$main_processor = $this->Application->recallObject('m_TagProcessor');

		$zones_sql = 'SELECT * FROM '.$zones_object->TableName.' WHERE ShippingTypeID='.$this->Application->GetVar('s_id').' ORDER BY Name ASC';
		$brackets_sql = 'SELECT * FROM '.$brackets_object->TableName.' WHERE ShippingTypeID='.$this->Application->GetVar('s_id').' ORDER BY Start ASC';

		$sql = 'SELECT * FROM '.$costs_object->TableName;
		$costs_array = $this->Conn->Query($sql, 'ShippingCostId');

		$zones = $this->Conn->Query($zones_sql, 'ZoneID');
		$brackets = $this->Conn->Query($brackets_sql, 'BracketId');

		$oddevenparam['odd'] = 'table-color1';
		$oddevenparam['even'] = 'table-color2';

		if(!$zones || !$brackets)
		{
			return '<tr class="'.$main_processor->Odd_Even($oddevenparam).'"><td>'.$this->Application->Phrase('la_NoZonesOrBrackets').'</td></tr>';
		}

		uasort($brackets, 'bracket_comp');

		if( $this->Application->GetLinkedVar('CostsTableAligment') )
		{
			$column_items = $brackets;
			$column_object =& $brackets_object;
			$column_params['header_caption'] = 'bracket_caption';
			$column_params['IdField'] = 'BracketId';
			$column_params['prefix'] = 'br';

			$row_items = $zones;
			$row_object =& $zones_object;
			$row_params['header_caption'] = 'zone_caption';
			$row_params['IdField'] = 'ZoneID';
			$row_params['prefix'] = 'z';
		}
		else
		{
			$column_items = $zones;
			$column_object =& $zones_object;
			$column_params['header_caption'] = 'zone_caption';
			$column_params['IdField'] = 'ZoneID';
			$column_params['prefix'] = 'z';

			$row_items = $brackets;
			$row_object =& $brackets_object;
			$row_params['header_caption'] = 'bracket_caption';
			$row_params['IdField'] = 'BracketId';
			$row_params['prefix'] = 'br';
		}

		$costs_table = '<tr class="'.$main_processor->Odd_Even($oddevenparam).'"><td>&nbsp;</td>';

		foreach($column_items as $id => $record)
		{
			$column_object->Load($id);
			$head_row_params = $column_params;
			$head_row_params['name'] = 'column_header';
			$costs_table .= $this->Application->ParseBlock($head_row_params);
		}
		$costs_table .= '</tr>';

		$cost_ids = Array();
		foreach($row_items as $id =>$record)
		{
			$costs_table .= '<tr class="'.$main_processor->Odd_Even($oddevenparam).'">';
			$row_object->Load($id);
			$head_row_params = $row_params;
			$head_row_params['name'] = 'row_header';
			$costs_table .= $this->Application->ParseBlock($head_row_params);
			foreach($column_items as $col_id => $col_record)
			{
				$res = false;

				foreach($costs_array as $cost_id => $cost_record)
				{
					if($cost_record[$row_params['IdField']] == $id && $cost_record[$column_params['IdField']] == $col_id)
					{
						$costs_object->SetDBFieldsFromHash($cost_record);
						$res = true;
						break;
					}
				}

				if($res == false)
				{
					$costs_object->Clear();
					$sql = 'SELECT MIN(ShippingCostId) FROM '.$costs_object->TableName;
					$new_id = $cost_ids ? min( $this->Conn->GetOne($sql) - 1, min($cost_ids) - 1 ) : 0;
					$costs_object->SetDBField( 'ShippingCostId', $new_id );
					$cost_ids[] = $new_id;
				}
				$column_object->Load($col_id);
				$costs_object->SetID($costs_object->GetDBField('ShippingCostId'));
				$cost_cell_params['name'] = 'cost_cell';

				$costs_table .= $this->Application->ParseBlock($cost_cell_params);
			}
			$costs_table .= '</tr>';
		}
		return $costs_table;
	}

	function HiddenSelection($params)
	{
		// $object = $this->getPrefixSpecial();

		$zones = $this->Application->GetVar('z');
		$brackets = $this->Application->GetVar('br');

		$ret = '';
		foreach($zones as $id => $record)
		{
			$ret .= '<input type="hidden" name="z['.$id.'][ZoneID]" value="'.$id.'">'."\n";
		}
		foreach ($brackets as $id => $record)
		{
			$ret .= '<input type="hidden" name="br['.$id.'][BracketId]" value="'.$id.'">'."\n";
		}
		return $ret;
	}

	function Order_PrintShippingTypes($params)
	{
		$weight = $this->Application->Parser->GetParam('weight_metric');
		$items = $this->Application->Parser->GetParam('items');
		$amount = $this->Application->Parser->GetParam('amount');
		$selected_id = $this->Application->Parser->GetParam('selected_id');
		$package_id = $this->Application->Parser->GetParam('package_num');

		// free promo shipping params if applicable, if not then the same as standard
		$promo_items = $this->Application->Parser->GetParam('promo_items');
		$promo_amount = $this->Application->Parser->GetParam('promo_amount');
		$promo_weight = $this->Application->Parser->GetParam('promo_weight_metric');

		$user_country_id = $this->Application->Parser->GetParam('user_country_id');
		$user_state_id = $this->Application->Parser->GetParam('user_state_id');
		$user_zip = $this->Application->Parser->GetParam('user_zip');
		$user_city = $this->Application->Parser->GetParam('user_city');
		$user_addr1 = $this->Application->Parser->GetParam('user_addr1');
		$user_addr2 = $this->Application->Parser->GetParam('user_addr2');
		$user_name = $this->Application->Parser->GetParam('user_name');

		$limit_types = $this->Application->Parser->GetParam('limit_types');

		$this->Application->recallObject('ShippingQuoteEngine'); // TODO: why call this here?

		/** @var ShippingQuoteCollector $quote_engine_collector */
		$quote_engine_collector = $this->Application->recallObject('ShippingQuoteCollector');

		$shipping_quote_params = Array (
			'dest_country'	=>	$user_country_id,
			'dest_state'	=>	$user_state_id,
			'dest_postal'	=>	$user_zip,
			'dest_city'		=>	$user_city,
			'dest_addr1'	=>	$user_addr1,
			'dest_addr2'	=>	$user_addr2,
			'dest_name'		=>	$user_name,
			'packages' 		=>	Array (
				Array (
					'package_key'	=>	'package1',
					'weight'		=>	$weight,
					'weight_unit'	=>	'KG',
					'length'		=>	'',
					'width'			=>	'',
					'height'		=>	'',
					'dim_unit'		=>	'IN',
					'packaging'		=>	'BOX',
					'contents'		=>	'OTR',
					'insurance'		=>	'0'
				),
			),
			'amount'		=>	$amount,
			'items'			=>	$items,
			'limit_types' 	=> 	$limit_types,
			'promo_params'	=>	Array (
				'items'		=>	$promo_items,
				'amount'	=>	$promo_amount,
				'weight'	=>	$promo_weight,
			)
		);

		$shipping_types = $quote_engine_collector->GetShippingQuotes($shipping_quote_params);

		$last_shippings = $this->Application->RecallVar('LastShippings');
		if ( $last_shippings ) {
			$last_shippings = unserialize($last_shippings);
		}

		/** @var OrdersItem $order_object */
		$order_object = $this->Application->recallObject('ord');

		$original_shipping = $order_object->GetDBField('ShippingInfo');
		$original_shipping = unserialize($original_shipping);
		$shipping_type_keys = array_keys($shipping_types);

		if(	getArrayValue($original_shipping, $package_id, 'ShippingId') &&
			( $this->Application->isAdminUser || in_array( $original_shipping[$package_id]['ShippingId'], $shipping_type_keys ) ) )
		{
			$original_shipping = $original_shipping[$package_id];
			$key = $original_shipping['ShippingId'];

			// When changing shipping type (via dropdown), then prefer current order's actual
			// shipping info over one from Shipping Quote Engines.
			if ( $this->Application->isAdminUser ) {
				$shipping_types[$key] = $original_shipping;
				$shipping_types[$key]['ShippingName'] = 'Original: ' . $original_shipping['ShippingName'];
			}

			$selected_id = $key;
		}

		$last_shippings[$package_id] = $shipping_types;

		if ( $this->Application->isAdminUser && isset($key) && $key ) {
			$orig_name = ltrim($last_shippings[$package_id][$key]['ShippingName'], 'Original: ');
			$last_shippings[$package_id][$key]['ShippingName'] = $orig_name;
		}
		$this->Application->StoreVar('LastShippings', serialize($last_shippings));

		$o = '';
		$def_block_params = Array();
		$def_block_params['name'] = $this->SelectParam($params, 'render_as,block');

		if ( !count($shipping_types) ) {
			$this->Application->SetVar('ItemShipmentsExists', 0);

			return '';
		}

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

		foreach ($shipping_types as $shipping_type) {
			if ( isset($shipping_type['InsuranceFee']) ) {
				$shipping_type['TotalCost'] += $shipping_type['InsuranceFee'];
			}

			$shipping_type['ShippingFree'] = ($shipping_type['TotalCost'] == 0) ? 1 : 0;

			$iso = $this->GetISO($params['currency']);
			$amount = $this->ConvertCurrency($shipping_type['TotalCost'], $iso);
			$amount = $lang->formatNumber($amount, 2);
			$shipping_type['TotalCost'] = $this->AddCurrencySymbol($amount, $iso);

			$block_params = array_merge($def_block_params, $shipping_type);
			$block_params['selected'] = $shipping_type['ShippingId'] == $selected_id ? 'selected' : '';

			if ( isset($params['selected_only']) && $block_params['selected'] == '' ) {
				continue;
			}

			$o .= $this->Application->ParseBlock($block_params);
		}

		return $o;
	}

	function AvailableTypes($params)
	{
		/** @var ShippingQuoteCollector $quote_engine_collector */
		$quote_engine_collector = $this->Application->recallObject('ShippingQuoteCollector');

		$types = $quote_engine_collector->GetAvailableShippingTypes();

		$o;
		foreach ($types as $a_type)
		{
			$block_params = $a_type;
			$block_params['name']	= $params['render_as'];
			$o .= $this->Application->ParseBlock($block_params);
		}
		return $o;
	}

	protected function ListGroups($params)
	{
		/** @var kDBItem $object */
		$object = $this->getObject($params);

		$o = '';
		$selected = trim($object->GetDBField('PortalGroups'), ',');
		$selected_arr = explode(',', $selected);

		$sql = 'SELECT GroupId, Name
				FROM ' . TABLE_PREFIX . 'UserGroups
				ORDER BY Name';
		$all_groups = $this->Conn->Query($sql, 'GroupId');

		$mode = array_key_exists('mode', $params) ? $params['mode'] : false;

		foreach ($all_groups as $a_group) {
			$is_selected = in_array($a_group['GroupId'], $selected_arr);
			$continue = $mode == 'selected' ? !$is_selected : $is_selected;

			if ( $continue ) {
				continue;
			}

			$block_params = $a_group;
			$block_params['name'] = $params['render_as'];
			$o .= $this->Application->ParseBlock($block_params);
		}

		return $o;
	}
}
