<?php
class ControllerSaleCanadapostShipping extends Controller {

    private $data = array();

    public function getData(&$route = false, &$data = false, &$output = false) {
        
        $this->load->language('sale/canadapost_shipping');

        $data['shipping_canadapost_status'] = false;

        if ($this->config->get('shipping_canadapost_status') && isset($data['shipping_code'])) {
            
            if (isset($this->session->data['success'])) {
                $data['success'] = $this->session->data['success'];
                unset($this->session->data['success']);
            } else {
                $data['success'] = '';
            }

           $shipping_code =  explode('.', $data['shipping_code']);
           if (strtolower($shipping_code[0]) == 'canadapost') {
              $data['shipping_canadapost_status'] = true;
              $data['text_shipment'] = $this->language->get('text_shipment');
              $data['shipment_href'] = $this->url->link('sale/canadapost_shipping/createShipment', 'user_token=' . $this->session->data['user_token']. '&order_id=' . $data['order_id'], true );
              $data['shipment_href'] = html_entity_decode($data['shipment_href'], ENT_QUOTES, 'UTF-8');
              $data['column_label'] =  $this->language->get('text_label');
              $data['error_product'] = $this->language->get('error_product');
              $data['text_tracking'] = $this->language->get('text_tracking');
              $data['text_get_label']   =   $this->language->get('text_get_label');
              $data['text_print_label']   =   $this->language->get('text_print_label');
           }
        }
        
    }

    public function createShipment() {
       
        $json = array();
        $this->load->language('sale/canadapost_shipping');

        if (isset($this->request->get['order_id']) && $this->request->get['order_id']) {

            $data = array();
            $data = array_merge($data,$this->load->language('sale/canadapost_shipping'));
            $this->load->model('localisation/zone');
            $this->load->model('localisation/weight_class');
            $this->load->model('sale/order');
            $this->load->model('extension/shipping/canadapost');

            $username = $this->config->get('shipping_canadapost_api_key');
            $password = $this->config->get('shipping_canadapost_api_password');
            $mailedBy = $this->config->get('shipping_canadapost_customer_number');

            $order_info = $this->model_sale_order->getOrder($this->request->get['order_id']);
            if ($order_info) {

                $shipping_method = isset($order_info['shipping_method']) && $order_info['shipping_method'] ? explode('-',$order_info['shipping_method']) : '';

                $shipping_code = trim($shipping_method[0]);
            
                $data['servicesDom'] = array(
                    'DOM.RP'  => $data['text_service'],
                    'DOM.EP'  => $data['text_service1'],
                    'DOM.XP'  => $data['text_service2'],
                    'DOM.XP.CERT'  => $data['text_service3'],
                    'DOM.PC'  => $data['text_service4'],
                    'DOM.DT'  => $data['text_service5'],
                    'DOM.LIB'  => $data['text_service6'],
                );
        
                $data['servicesUsa'] = array(
                'USA.EP'  => $data['text_service7'],
                        'USA.PW.ENV'  => $data['text_service8'],
                        'USA.PW.PAK'  => $data['text_service9'],
                        'USA.PW.PARCEL'  => $data['text_service11'],
                        'USA.XP' => $data['text_service14'],
                        'USA.TP' => $data['text_service13'],
                );
            
                $data['servicesInn'] = array(
                'INT.XP'  => $data['text_INT_XP'],
                        'INT.IP.AIR'  => $data['text_INT_IP_AIR'],
                        'INT.IP.SURF'  => $data['text_INT_IP_SURF'],
                        'INT.SP.AIR'  => $data['text_INT_SP_AIR'],
                        'INT.PW.PARCEL'  => $data['text_INT_PW_PARCEL'],
                        'INT.SP.SURF'  => $data['text_INT_SP_SURF'],
                        'INT.TP'  => $data['text_INT_TP'],
                );

                $data['services'] = array_merge($data['servicesDom'], $data['servicesUsa'],$data['servicesInn']);

                if ($shipping_code && in_array($shipping_code, $data['services']) ) {
                   
                    $code = array_search($shipping_code, $data['services']);
                } else {
                    $code = '';
                }
               
                if (!$this->config->get('shipping_canadapost_test')) {
                    //Url for Production mode
                    $service_url = 'https://soa-gw.canadapost.ca/rs/' . $mailedBy . '/ncshipment';
                } else {
                    //Url for Development mode
                    $service_url = 'https://ct.soa-gw.canadapost.ca/rs/' . $mailedBy . '/ncshipment';
                }

                if ($this->config->get('shipping_canadapost_origin_address') == 'custom') {
                    $originPostalCode = str_replace(" ", "", $this->config->get('shipping_canadapost_postcode'));
                } else {
                    $originPostalCode = str_replace(" ", "", $this->config->get('config_geocode'));
                }

                $requestedShippingPoint = trim($originPostalCode);

                $mailingDate = date('Y-M-D');
                $xmlRequest  = '<?xml version="1.0" encoding="UTF-8"?>';
                $xmlRequest .= '<non-contract-shipment xmlns="http://www.canadapost.ca/ws/ncshipment-v4">';
                $xmlRequest .=    '<requested-shipping-point>' . $requestedShippingPoint . '</requested-shipping-point>';
                $xmlRequest .=    '<delivery-spec>';
                $xmlRequest .=        '<service-code>' . $code . '</service-code>';
                $xmlRequest .=        '<sender>';
                $xmlRequest .=            '<company>' . $this->config->get('config_name') . '</company>';
                $xmlRequest .=            '<contact-phone>' . $this->config->get('config_telephone') . '</contact-phone>';

                if ($this->config->get('shipping_canadapost_origin_address') == 'custom') {
                    $zone = $this->model_localisation_zone->getZone($this->config->get('shipping_canadapost_origin_zone'));

                    $xmlRequest .=            '<address-details>';
                    $xmlRequest .=                '<address-line-1>' . $this->config->get('shipping_canadapost_address_line1') . '</address-line-1>';
                    $xmlRequest .=                '<city>' . $this->config->get('shipping_canadapost_city') . '</city>';
                    $xmlRequest .=                '<prov-state>' .  $zone['code'] . '</prov-state>';
                    $xmlRequest .=                '<postal-zip-code>' . strtoupper($requestedShippingPoint) . '</postal-zip-code>';
                    $xmlRequest .=            '</address-details>';
                } else {
                    $zone = $this->model_localisation_zone->getZone($this->config->get('config_zone_id'));
                    
                    $xmlRequest .=            '<address-details>';
                    $xmlRequest .=                '<address-line-1>' . $this->config->get('config_address') . '</address-line-1>';
                    $xmlRequest .=                '<city>' . $this->config->get('config_address') . '</city>';
                    $xmlRequest .=                '<prov-state>' .  $zone['code'] . '</prov-state>';
                    $xmlRequest .=                '<postal-zip-code> ' . strtoupper($requestedShippingPoint)  . '</postal-zip-code>';
                    $xmlRequest .=            '</address-details>';
                }

                $xmlRequest .=        '</sender>';
                $xmlRequest .=        '<destination>';
                $xmlRequest .=            '<name>' . $order_info['firstname'] . ' ' . $order_info['lastname'] . '</name>';
                $xmlRequest .=            '<company>' . $order_info['shipping_company'] . '</company>';
                $xmlRequest .=            '<client-voice-number>' . $order_info['telephone'] . '</client-voice-number>';
                $xmlRequest .=            '<address-details>';
                $xmlRequest .=                '<address-line-1>' . $order_info['shipping_address_1'] . '</address-line-1>';
                
                $xmlRequest .=                '<city>' . $order_info['shipping_city'] . '</city>';
                $xmlRequest .=                '<prov-state>' . $order_info['shipping_zone_code'] . '</prov-state>';
                $xmlRequest .=                '<country-code>' . $order_info['shipping_iso_code_2'] . '</country-code>';
                $xmlRequest .=                '<postal-zip-code>' . $order_info['shipping_postcode'] . '</postal-zip-code>';
                $xmlRequest .=            '</address-details>';
                $xmlRequest .=        '</destination>';
               
               if ($code && substr($code,0,3) == "INT" || substr($code,0,3) == "USA") {
                $xmlRequest .=        '<options>';
                $xmlRequest .=            '<option>';     
                $xmlRequest .=                '<option-code>RASE</option-code>';
                $xmlRequest .=            '</option>';
                $xmlRequest .=        '</options>';
               }
               
               $weightClassId = $this->model_localisation_weight_class->getWeightClassDescriptionByUnit('kg');
               
                if(isset($this->request->post['products']) && is_array($this->request->post['products']) && !empty($this->request->post['products'])) {
                    
                    $product_info = array();
                    $products = $this->request->post['products'];

                    foreach($products as $product_id) {
                        $label = $this->model_extension_shipping_canadapost->getShipment($this->request->get['order_id'] ,$product_id);
                        if ($label)
                          $json['label_exists'] = $this->language->get('text_generated');
                        else   
                          $json['label_exists'] = '';
                        
                        $product_info = $this->model_extension_shipping_canadapost->getOrderedProduct($this->request->get['order_id'], $product_id);

                        if (round($product_info['weight'],2) <= 0 || round($product_info['height']) <= 0 || round($product_info['length'],2) <= 0 || round($product_info['width'], 2) <= 0) {
                        
                           $json['error'] = sprintf($this->language->get('error_dimension'), $product_info['name']); 
                        }
                        if (!isset($json['error']) && !$label) {
                            
                            $weight = $this->weight->convert($product_info['weight'], $product_info['weight_class_id'], $weightClassId['weight_class_id']);

                            $total_weight = $weight * $product_info['quantity'];
                            $xmlProductRequest = '';
                            
                            $xmlProductRequest .=        '<parcel-characteristics>';
                            $xmlProductRequest .=            '<weight>' . round($total_weight,2). '</weight>';
                            $xmlProductRequest .=            '<dimensions>';
                            $xmlProductRequest .=                '<length>' . round($product_info['length'],2) . '</length>';
                            $xmlProductRequest .=                '<width>' . round($product_info['width'],2) . '</width>';
                            $xmlProductRequest .=                '<height>' . round($product_info['height'],2) . '</height>';
                            $xmlProductRequest .=            '</dimensions>';
                            $xmlProductRequest .=        '</parcel-characteristics>';
                            if ($code && substr($code,0,3) == "INT" || substr($code,0,3) == "USA") {
                                $xmlProductRequest .=        '<customs>';
                                $xmlProductRequest .=        '<currency>CAD</currency>';
                                $xmlProductRequest .=        '<reason-for-export>SOG</reason-for-export>';
                                $xmlProductRequest .=        '<sku-list>';
                                $xmlProductRequest .=          '<item>';
                                $xmlProductRequest .=              '<customs-number-of-units>' . $product_info['quantity'] . '</customs-number-of-units>';
                                $xmlProductRequest .=              '<customs-description>custom demo description</customs-description>';
                                $xmlProductRequest .=              '<unit-weight>' . round($weight,2) . '</unit-weight>';
                                $xmlProductRequest .=              '<customs-value-per-unit>100</customs-value-per-unit>';
                                $xmlProductRequest .=        '</item>';
                                $xmlProductRequest .=        '</sku-list>';
                                $xmlProductRequest .=        '</customs>';
                            }
                            $xmlProductRequest .=        '<preferences>';
                            $xmlProductRequest .=            '<show-packing-instructions>true</show-packing-instructions>';
                            $xmlProductRequest .=        '</preferences>';
                            $xmlProductRequest .=        '<references>';
                            $xmlProductRequest .=            '<cost-centre>ccent</cost-centre>';
                            $xmlProductRequest .=            '<customer-ref-1>custref1</customer-ref-1>';
                            $xmlProductRequest .=            '<customer-ref-2>custref2</customer-ref-2>';
                            $xmlProductRequest .=        '</references>';
                            $xmlProductRequest .=    '</delivery-spec>';
                            $xmlProductRequest .= '</non-contract-shipment>';
    
                            $xmlProductRequest = $xmlRequest . $xmlProductRequest;
                            
                            // Create CreateShipment request xml
                            $curl = curl_init($service_url); // Create REST Request
                            curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, true);
                            curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, 2);
                            curl_setopt($curl, CURLOPT_CAINFO, realpath(dirname($_SERVER['SCRIPT_FILENAME'])) . '/canadapost/cert/cacert.pem'); // Signer Certificate in PEM format
                            curl_setopt($curl, CURLOPT_POST, true);
                            curl_setopt($curl, CURLOPT_POSTFIELDS, $xmlProductRequest);
                            curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
                            curl_setopt($curl, CURLOPT_HTTPAUTH, CURLAUTH_BASIC);
                            curl_setopt($curl, CURLOPT_USERPWD, $username . ':' . $password);
                            curl_setopt($curl, CURLOPT_HTTPHEADER, array('Content-Type: application/vnd.cpc.ncshipment-v4+xml', 'Accept: application/vnd.cpc.ncshipment-v4+xml'));
	
                          
                            $curl_response = curl_exec($curl); // Execute REST Request

                            $responseCode = curl_getinfo($curl,CURLINFO_HTTP_CODE);
                            curl_close($curl);
                            if ($responseCode == 0 ) {
                                $curl = curl_init($service_url); // Create REST Request
                                curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, true);
                                curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, 2);
                                curl_setopt($curl, CURLOPT_CAINFO, realpath(dirname($_SERVER['SCRIPT_FILENAME'])) . '/canadapost/cert/cacert.pem'); // Signer Certificate in PEM format
                                curl_setopt($curl, CURLOPT_POST, true);
                                curl_setopt($curl, CURLOPT_POSTFIELDS, $xmlProductRequest);
                                curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
                                curl_setopt($curl, CURLOPT_HTTPAUTH, CURLAUTH_BASIC);
                                curl_setopt($curl, CURLOPT_USERPWD, $username . ':' . $password);
                                curl_setopt($curl, CURLOPT_HTTPHEADER, array('Content-Type: application/vnd.cpc.ncshipment-v4+xml', 'Accept: application/vnd.cpc.ncshipment-v4+xml'));
        
                              
                                $curl_response = curl_exec($curl); // Execute REST Request
    
                                $responseCode = curl_getinfo($curl,CURLINFO_HTTP_CODE);
                                curl_close($curl);
                            }
                         
                           

                                libxml_use_internal_errors(true);
                                $xml = simplexml_load_string('<root>' . preg_replace('/<\?xml.*\?>/','',$curl_response) . '</root>');
                                
                                if (!$xml) {
                                    foreach(libxml_get_errors() as $error) {
                                        $json['error']  = $error->message;
                                    }
                                } else {
                                    if ($xml->{'non-contract-shipment-info'} ) {	
                                        $shipment = $xml->{'non-contract-shipment-info'}->children('http://www.canadapost.ca/ws/ncshipment-v4');
                                        if ( $shipment->{'shipment-id'} ) {
                                            $json['success'] = $this->language->get('text_success');
                                            $this->session->data['success'] =  $this->language->get('text_success');
                                            $json['shipment'][$product_id] = array (
                                                'shipment_id'   => (array)$shipment->{'shipment-id'},
                                                'tracking_pin'  => (array)$shipment->{'tracking-pin'},
                                            );
                                            foreach ( $shipment->{'links'}->{'link'} as $link ) {
                                                if ($link->attributes()->{'rel'} == 'label') {
                                                    $service_url = $link->attributes()->{'href'};

                                                    $curl = curl_init($service_url); // Create REST Request
                                                    curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, true);
                                                    curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, 2); 
                                                    curl_setopt($curl, CURLOPT_CAINFO, realpath(dirname($_SERVER['SCRIPT_FILENAME'])) . '/canadapost/cert/cacert.pem'); // Mozilla cacerts
                                                    curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
                                                    curl_setopt($curl, CURLOPT_HTTPAUTH, CURLAUTH_BASIC);
                                                    curl_setopt($curl, CURLOPT_USERPWD, $username . ':' . $password);
                                                    curl_setopt($curl, CURLOPT_HTTPHEADER, array('Accept:application/pdf', 'Accept-Language:en-CA'));
                                                    $curl_response = curl_exec($curl); // Execute REST Request

                                                    $contentType =  curl_getinfo($curl,CURLINFO_CONTENT_TYPE);

                                                    if ( strpos($contentType, 'application/pdf' ) !== FALSE ) {
                                                        // Writing binary response to file
                                                        $fileName = 'Label_' . $product_id . '.pdf';

                                                        $filePath = DIR_IMAGE . 'canadapost_shipping/' . $this->request->get['order_id'] . '/' . $product_id;
                                                        
                                                        if (!is_dir($filePath))
                                                            mkdir($filePath,0777, true);
                                                        
                                                        file_put_contents($filePath . '/' . $fileName , $curl_response);
                                                        $shipment_array = array (
                                                            'order_id'  => $this->request->get['order_id'],
                                                            'product_id'    => $product_id,
                                                            'shipping_label' => $fileName,
                                                            'tracking_no'   =>  $shipment->{'tracking-pin'},

                                                        );
                                                        $this->model_extension_shipping_canadapost->addShipment($shipment_array);
                                                    } elseif (strpos($contentType, 'xml' ) > -1 )   {
                                                        // Example of using SimpleXML to parse xml error response
                                                        libxml_use_internal_errors(true);
                                                        $xml = simplexml_load_string('<root>' . preg_replace('/<\?xml.*\?>/','',$curl_response) . '</root>');
                                                        if (!$xml) {
                                                            echo 'Failed loading XML' . "\n";
                                                            echo $curl_response . "\n";
                                                            foreach(libxml_get_errors() as $error) {
                                                                echo "\t" . $error->message;
                                                            }
                                                        } else {	
                                                            if ($xml->{'messages'} ) {					
                                                                $messages = $xml->{'messages'}->children('http://www.canadapost.ca/ws/messages');		
                                                                foreach ( $messages as $message ) {
                                            
                                                                    $json['error_code_label'][$product_id] = $message->code;
                                                                    $json['error_msg_label'][$product_id] = (array)$message->description;
                                                                }
                                                            }
                                                        }
                                                    } else {
                                                        
                                                        $json['error_content']  = 'Unknown Content Type: ' . $contentType ;
                                                    }
                                                
                                                curl_close($curl);
                                                
                                            }  	
                                        }
                                    }
                                }
                                if ($xml->{'messages'} ) {					
                                    $messages = $xml->{'messages'}->children('http://www.canadapost.ca/ws/messages');		
                                    foreach ( $messages as $message ) {
                                        $json['error_code'][$product_info['name']] = $message->code;
                                        $json['error_msg'][$product_info['name']] = $message->description;
                                    }
                                }
                            }
                        
                    }    
                }
            }   
            }    
        }
       
        $this->response->addHeader('Content-Type: application/json');
		$this->response->setOutput(json_encode($json));
    }
}