<?php

namespace OfficeBrain\Bundle\ShippingEstimatorBundle\Manager\AbstractManager;

use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Translation\Translator;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\Session\Session;
use Symfony\Component\HttpFoundation\Session\Flash\FlashBag;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
use Symfony\Component\HttpFoundation\JsonResponse;

abstract class ShippingEstimatorAbstract
{
	/**
	 * @author Employee Id: 4471
	 * OB eCommerce Product - Requestinfo
	 * Initialize the required variable on class load
	 */
	public function __construct($entityManager, $request, $session, $productDetailService)
	{
		$this->entityManager = $entityManager;
		$this->request = $request;
		$this->sessionManager = $session;
		$this->productDetailService = $productDetailService;
		
		$this->projectSetting = $this->request->get('project_setting');
		$this->instanceId = $this->projectSetting['instance_id'];
		$this->instanceType = $this->projectSetting['instance_type'];
		$this->userId = $this->projectSetting['user_id'];
		$this->cultureId = $this->projectSetting['culture_id'];
		$this->cultureCode = $this->projectSetting['culture_code'];
	}
	
	public function __destruct()
	{
		unset($this->entityManager);
		unset($this->request);
		unset($this->sessionManager);
		unset($this->productDetailService);
		unset($this->projectSetting);
		unset($this->instanceId);
		unset($this->instanceType);
		unset($this->userId);
		unset($this->cultureId);
		unset($this->cultureCode);
	}
	
	public function getProductDetailBySlug($productSlug)
	{
		return $this->productDetailService->getProductDetailBySlug($productSlug,  $this->cultureCode);
	}
	
	public function getProductDetailByIdForShipping($productId)
	{
		$productDetail= $this->productDetailService->getProductDetailById($productId, $this->cultureCode);
		if(array_key_exists('shipping_information', $productDetail[$productId]))
		{
			$shippingInformation=array_merge($productDetail[$productId]['shipping_information'],array('shipper'=>$productDetail[$productId]['supplier']));
			return $shippingInformation;
		}
		else {
			return false;
		}
		
	}
	
	public function getProductDetailById($productId)
	{
		return $this->productDetailService->getProductDetailById($productId, $this->cultureCode);
	}
	
	public function getProductDetailForShipping($productId,$qty)
	{
		$shippingInformation = $this->getProductDetailByIdForShipping($productId);
		//print_r($shippingInformation);
		if($shippingInformation!=false)
		{
			$state ='';
			$city = '';
			$carton_height=0;
			$carton_length=0;
			$carton_width=0;
			$qtyPerCartoon=0;
			$productWeight = 0;
			$weightArray=array();
			$totalWeightForShipping = 0;
			$fob=$shippingInformation["free_on_board"];
			$qtyPerCartoon=$shippingInformation["quantity_in_carton"];
			
			if(array_key_exists('carton', $shippingInformation))
			{
				$cartonHeight=$shippingInformation["carton"]["height"]["param"];
				$cartonLength=$shippingInformation["carton"]["length"]["param"];
				$cartonWidth=$shippingInformation["carton"]["width"]["param"];
				$cartonWeight=$shippingInformation["carton"]["weight"]["param"];
			}
			if(isset($shippingInformation["product"]["weight"]["unit"])){
				if($shippingInformation["product"]["weight"]["unit"]=="OZ"){
					$ozToLb = 0.0625; // 1 oz = 0.0625
					$pWeight = $shippingInformation["product"]["weight"]["param"]*$ozToLb; 
					$shippingInformation["product"]["weight"]["param"] = $pWeight;
				}
			}
			$productWeight = $shippingInformation["product"]["weight"]["param"];
			if($this->userId!='0')
				$weightCalFromCartoon = $this->projectSetting['configuration_rule']['transaction']['shipping_estimator']['option']['registered_user']['option']['rate']['option']['calculate_product_weight_by_cartoon_weight'];
			else
				$weightCalFromCartoon = $this->projectSetting['configuration_rule']['transaction']['shipping_estimator']['option']['guest_user']['option']['rate']['option']['calculate_product_weight_by_cartoon_weight'];
			
			if($weightCalFromCartoon == 1)
			{
				//calcultate product weight according carton weight
				if ($qtyPerCartoon != 0 && ($cartonWeight != '' && $cartonWeight!= '0'))
				{
					$unitProductWeightAccorCartoon = $cartonWeight/$qtyPerCartoon;
					$noOfBox = ceil($qty / $qtyPerCartoon);
				}
				else
				{
					// qty per carton is missing or cartonWeight is missing
					return array('status'=>'error','error'=>'product_detail_error');
				}
				if($noOfBox>150)
				{
					return array('status'=>'error','error'=>'no_of_box_error');
				}
				if ($noOfBox > 1) {
					$pack = array();
					$totalQty = $qty;
					$k = 0;
					while ($totalQty != 0) {
						if ($totalQty <= $qtyPerCartoon) {
							$pack[$k] = $totalQty;
							$weightArray[$k] = ($totalQty * $unitProductWeightAccorCartoon);
							$totalWeightForShipping= $weightArray[$k]+$totalWeightForShipping;
							$totalQty = 0;
						} else {
							$pack[$k] = $qtyPerCartoon;
							$weightArray[$k] = $cartonWeight;
							$totalQty = $totalQty - $qtyPerCartoon;
						}
						$k++;
					}
				} else {
					$weightArray[0] =  $qty * $unitProductWeightAccorCartoon;
					$totalWeightForShipping= $weightArray[0];
				}
			}
			else
			{
				if(!is_numeric($productWeight) || $productWeight==0)
				{
					// weight is missing or not numeric then return error
					return array('status'=>'error','error'=>'product_detail_error');
				}
				if($this->userId!='0')
					$addBoxWeight = $this->projectSetting['configuration_rule']['transaction']['shipping_estimator']['option']['registered_user']['option']['rate']['option']['add_package_weight'];
				else
					$addBoxWeight= $this->projectSetting['configuration_rule']['transaction']['shipping_estimator']['option']['guest_user']['option']['rate']['option']['add_package_weight'];
				
				// calcutation according product weight
				$qtyweight = $qty * $productWeight;
				if($qtyPerCartoon!=0)
				{
					$noOfBox=ceil($qty/$qtyPerCartoon);
					if($addBoxWeight==1)
						$totalWeight=$qtyweight+($noOfBox*$cartonWeight);
					else
						$totalWeight=$qtyweight; // change for aakron because we are not adding cartoon weight in this - emp 4471
				}
				else
				{
					$noOfBox=ceil($qtyweight/70);
					$noOfBoxFedex=ceil($qtyweight/70);
					$noOfBoxUPS=ceil($qtyweight/70);
					$totalWeight=$qtyweight;
				}
				$totalWeightForShipping= $totalWeight;
				if($noOfBox>150)
				{
					return array('status'=>'error','error'=>'no_of_box_error');
				}
				if($noOfBox>1)
				{
					$pack=array();
					$totalQty=$qty;
					$k=0;
					while($totalQty!=0)
					{
						if($totalQty <= $qtyPerCartoon)
						{
							$pack[$k]=$totalQty;
							if($addBoxWeight==1)
								$weightArray[$k]=($totalQty*$productWeight)+$cartonWeight;
							else
								$weightArray[$k]=($totalQty*$productWeight); // change for aakron because we are not adding cartoon weight in this - emp 4471
	
							$totalQty=0;
						}
						else
						{
							$pack[$k]=$qtyPerCartoon;
							if($addBoxWeight==1)
								$weightArray[$k]=($qtyPerCartoon*$productWeight)+$cartonWeight;
							else
								$weightArray[$k]=($qtyPerCartoon*$productWeight);// change for aakron because we are not adding cartoon weight in this - emp 4471
							$totalQty=$totalQty-$qtyPerCartoon;
						}
						$k++;
					}
				}
				else
				{
					$weightArray[0]=$totalWeight;
				}
			}
			
			$state = '' ;
			$zipcode='';
			$country='' ;
			$fobDetail=explode(' ', $fob);
			$fobDetail=array_reverse($fobDetail);// emp id -> 4471 did reverse array because it may possible that fob have more then 3 element in array so  
			if(count($fobDetail)==4)
			{
				$city=$fobDetail[3];
			}
			
			if(is_array($fobDetail) && key_exists('2', $fobDetail))
			{
				$state= $fobDetail[2];
			}
			if(is_array($fobDetail) && key_exists('1', $fobDetail))
			{
				$zipcode=$fobDetail[1];
			}
			if(is_array($fobDetail) && key_exists('0', $fobDetail))
			{
				$country=$fobDetail[0];
			}
			
			if($state == '' || $zipcode=='' || $country=='')
			{
				// proprer FOB is missing then return error
				return array('status'=>'error','error'=>'fob_error');
			}
				
			$productShippingDetail = array(
											'cartonHeight'=>$cartonHeight,
											'cartonLength'=>$cartonLength,
											'cartonWidth'=>$cartonWidth,
											'cartonWeight'=>$cartonWeight,
					
											'qtyPerCartoon'=>$qtyPerCartoon,
											'productWeight'=>$productWeight,
											'totalWeight'=>$weightArray,
											'totalWeightForShipping'=>$totalWeightForShipping,
											'noOfBox'=>$noOfBox,
											
											'city'=>$city,
											'state'=>$state,
											'zipcode'=>$zipcode,
											'country'=>$country,
											
											'shipper'=>$shippingInformation['shipper']
										);
			
			$finalproductShippingDetail = $this->splitDownThePackage($productShippingDetail, $qty);
			if(isset($finalproductShippingDetail['error'])){
				return array('status'=>'error','error'=>'other','error_msg'=>$finalproductShippingDetail['error']);
			}
			return array('status'=>'success','data'=>$finalproductShippingDetail);
		}
		else
		{
			return array('status'=>'error','error'=>'product_detail_error');
		}
	}
	
	private function splitDownThePackage($productShippingDetail, $qty)
	{
	    $maxWeight     = 150; // UPS max weight limit
	    $cartonWeight  = $productShippingDetail['cartonWeight'];
	    $productWeight = $productShippingDetail['productWeight'];
	    $qtyPerCartoon = !empty($productShippingDetail['qtyPerCartoon'])
	        ? (int)$productShippingDetail['qtyPerCartoon']
	        : 0;
	    $orderQty = $qty;
	    // Max qty allowed by UPS weight limit
	    $maxQtyByWeight = floor(($maxWeight - $cartonWeight) / $productWeight);

	    if ($maxQtyByWeight <= 0) {
	        return array(
	            'error' => 'Single product exceeds UPS package limit.'
	        );
	    }

	    // Respect supplier carton capacity
	    if ($qtyPerCartoon > 0) {
	        $maxQtyPerBox = min($maxQtyByWeight, $qtyPerCartoon);
	    } else {
	        $maxQtyPerBox = $maxQtyByWeight;
	    }
	    $packages = [];
	    $remainingQty = $orderQty;
	    while ($remainingQty > 0) {

	        $qtyInBox = min($maxQtyPerBox, $remainingQty);
	        $boxWeight = $cartonWeight + ($productWeight * $qtyInBox);
	        $packages[] = round($boxWeight, 2);
	        $remainingQty -= $qtyInBox;
	    }

	    $productShippingDetail['totalWeight']=$packages; 
	    $productShippingDetail['totalWeightForShipping']=array_sum($packages); 
	    $productShippingDetail['noOfBox']=count($packages); 
	    return $productShippingDetail;
	}

	public function callRequest($productDetail,$shippinEstiConfi,$callFrom)
	{
	}
	
	
	/**
	 * @author Employee Id: 4471
	 * To check whether shipping detail Available for product or not
	 * @param integer productId
	 */
	public function checkShippingDetailAvailable($productId)
	{
		$productDetail= $this->productDetailService->getProductDetailById($productId, $this->cultureCode);
		$status = true;
		if(array_key_exists('shipping_information', $productDetail[$productId]))
		{
			$shippingInformation=array_merge($productDetail[$productId]['shipping_information'],array('shipper'=>$productDetail[$productId]['supplier']));
			if($shippingInformation!=false)
			{
				$productWeight = $shippingInformation["product"]["weight"]["param"];
	
				if(!is_numeric($productWeight) || $productWeight==0)
				{
					// weight is missing or not numeric then return error
					$status= false;
				}
				$fob=$shippingInformation["free_on_board"];
				$state = '' ;
				$zipcode='';
				$country='' ;
				$fobDetail=explode(' ', $fob);
				$fobDetail=array_reverse($fobDetail);// emp id -> 4471 did reverse array because it may possible that fob have more then 3 element in array so
				if(is_array($fobDetail) && key_exists('2', $fobDetail))
				{
					$state= $fobDetail[2];
				}
				if(is_array($fobDetail) && key_exists('1', $fobDetail))
				{
					$zipcode=$fobDetail[1];
				}
				if(is_array($fobDetail) && key_exists('0', $fobDetail))
				{
					$country=$fobDetail[0];
				}
	
				if($state == '' || $zipcode=='' || $country=='')
				{
					// proprer FOB is missing then return error
					$status= false;
				}
			}
			else
			{
				$status= false ;
			}
		}
		else {
			$status= false;
		}
		return $status;
	
	}
}
