<?php
/*
 #########################################################################
 #                       xt:Commerce Shopsoftware
 # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 #
 # Copyright 2021 xt:Commerce GmbH All Rights Reserved.
 # This file may not be redistributed in whole or significant part.
 # Content of this file is Protected By International Copyright Laws.
 #
 # ~~~~~~ xt:Commerce Shopsoftware IS NOT FREE SOFTWARE ~~~~~~~
 #
 # https://www.xt-commerce.com
 #
 # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 #
 # @copyright xt:Commerce GmbH, www.xt-commerce.com
 #
 # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 #
 # xt:Commerce GmbH, Maximilianstrasse 9, 6020 Innsbruck
 #
 # office@xt-commerce.com
 #
 #########################################################################
 */

defined('_VALID_CALL') or die('Direct Access is not allowed.');

require_once _SRV_WEBROOT . _SRV_WEB_PLUGINS. 'xt_ship_and_track/classes/constants.php';
require_once _SRV_WEBROOT . _SRV_WEB_PLUGINS. 'xt_ship_and_track/classes/class.xt_tracking.php';

require_once _SRV_WEBROOT . _SRV_WEB_PLUGINS. 'xt_ship_and_track/classes/class.xt_ship_and_track_layoutPart.php';

global $db;
$xt_sat_version = $db->GetOne("SELECT `version` FROM ".TABLE_PLUGIN_PRODUCTS." WHERE `code` = 'xt_ship_and_track'");
define('SHIP_AND_TRACK_PLUGIN_VERSION', $xt_sat_version);

// TABLE_SHIPCLOUD_SETTINGS
$sql = 'SELECT `value` FROM '.TABLE_SHIPCLOUD_SETTINGS. ' WHERE `key` = ?';
$a = $db->GetOne($sql, array(KEY_SHIPCLOUD_SANDBOX));
define('XT_SHIPCLOUD_SANDBOX',  $a==1 ? 1:0);

$a = $db->GetOne($sql, array(KEY_SHIPCLOUD_API_KEY_LIVE));
define('XT_SHIPCLOUD_API_KEY_LIVE',  $a ? $a:'');

$a = $db->GetOne($sql, array(KEY_SHIPCLOUD_API_KEY_SANDBOX));
define('XT_SHIPCLOUD_API_KEY_SANDBOX',  $a ? $a:'');

$a = $db->GetOne($sql, array(KEY_SHIPCLOUD_SANDBOX));
if(XT_SHIPCLOUD_SANDBOX==1)
{
    define('XT_SHIPCLOUD_API_KEY', XT_SHIPCLOUD_API_KEY_SANDBOX);
}
else {
    define('XT_SHIPCLOUD_API_KEY', XT_SHIPCLOUD_API_KEY_LIVE);
}

$a = $db->GetOne($sql, array(KEY_SHIPCLOUD_BANK_ACCOUNT_HOLDER));
define('XT_SHIPCLOUD_BANK_ACCOUNT_HOLDER',  $a ? $a:'');

$a = $db->GetOne($sql, array(KEY_SHIPCLOUD_BANK_NAME));
define('XT_SHIPCLOUD_BANK_NAME',  $a ? $a:'');

$a = $db->GetOne($sql, array(KEY_SHIPCLOUD_BANK_ACCOUNT_NUMBER));
define('XT_SHIPCLOUD_BANK_ACCOUNT_NUMBER',  $a ? $a:'');

$a = $db->GetOne($sql, array(KEY_SHIPCLOUD_BANK_CODE));
define('XT_SHIPCLOUD_BANK_CODE',  $a ? $a:'');


class xt_ship_and_track extends xt_ship_and_track_layoutPart {

    private $_master_key = 'id';

    function setPosition($position)
    {
        $this->position = $position;
    }

    function _getParams()
    {
        $header = [];
        $params = [];

        $this->getdefaultParams($header, $params);

        //$params['PageSize'] = 2;

        if (!$this->url_data['edit_id'])
        {
            $rowActionsFunctions = array();
            $rowActions = [];

            if (count($rowActionsFunctions) > 0) {
                $params['rowActions'] = $rowActions;
                $params['rowActionsFunctions'] = $rowActionsFunctions;
            }

            if (count($rowActions) > 0) {
                $params['rowActions'] = $rowActions;
                $params['rowActionsFunctions'] = $rowActionsFunctions;
            }
        }

        return $params;
    }

    function _unset($id = 0)
    {
        return false;
    }

    function deleteOrder($data)
    {
        $cascadeTracking = $data['cascade'];

        $r = new stdClass();
        $r->success = false;
        $r->msg = false;
        $r->errorMsg = false;

        global $db;

        $tracking = tracking::getTrackingForOrder($data['orders_id'],$data['tracking_code']);

        if($tracking[0])
        {
            $shipper_code = $tracking[0]['shipper_code'];
            if(strpos($shipper_code, 'shipcloud-') === 0)
            {
                $shipper_code = 'shipcloud';
            }
            switch($shipper_code)
            {
                case 'shipcloud':
                    try
                    {
                        shipcloud_api::getInstance(XT_SHIPCLOUD_API_KEY)
                            ->shipmentDelete($data['tracking_code']);

                        $db->Execute("DELETE FROM ".TABLE_SHIPCLOUD_LABELS." where `".COL_SHIPCLOUD_LABEL_ID."` = ?", array($data[COL_TRACKING_CODE]));

                        if ($cascadeTracking) // 312311 - Der Auftrag kann nicht gelöscht werden.
                        {
                            $xtTracking = new xt_tracking();
                            $data['cascade'] = false;
                            $xtTracking->deleteTracking($data);
                        }
                    }
                    catch (Exception $e)
                    {
                        $r->errorMsg = $e->getMessage();
                        $r->msg = $e->getMessage();
                        $r->success = false;
                        return json_encode($r);
                    }

                    $r->success = true;
                    $r->msg =__define('TEXT_SUCCESS');
                    return json_encode($r);

                    break;
            }
        }
        $r->success = false;
        $r->errorMsg = 'Sendung nicht gefunden';
        $r->msg =__define('TEXT_ALERT');
        return json_encode($r);
    }

    public function updateStatus($data)
    {
        global $db;

        $r = new stdClass();
        $r->success = false;
        $r->msg = false;
        $r->errorMsg = false;

        if($data['tracking_code'] == 'refresh_order')
        {
            return $this->updateStatusForOrder($data['orders_id']);
        }

        try {

            $tracking = tracking::getTrackingForOrder($data['orders_id'],$data['tracking_code']);

            if($tracking[0])
            {
                $shipper_code = $tracking[0]['shipper_code'];
                if(strpos($shipper_code, 'shipcloud-') === 0)
                {
                    $shipper_code = 'shipcloud';
                }
                switch($shipper_code)
                {
                    case 'shipcloud':
                        //$sc_id = $db->GetOne("SELECT ".COL_SHIPCLOUD_LABEL_ID. " FROM ".TABLE_SHIPCLOUD_LABELS. " WHERE ".COL_SHIPCLOUD_LABEL_ID_PK."=?", array($tracking[0]['id']));
                        $responseRead = shipcloud_api::getInstance(XT_SHIPCLOUD_API_KEY)
                            ->shipmentRead($data['tracking_code']);
                        $packages = $responseRead->packages();
                        $latestEvent = $packages[0]->tracking_events[0];
                        foreach($packages[0]->tracking_events as $te)
                        {
                            $dtLatest = new DateTime($latestEvent->timestamp);
                            $dtCurrent = new DateTime($te->timestamp);
                            if($dtCurrent > $dtLatest)
                            {
                                $latestEvent = $te;
                            }
                        }
                        $r->msg = self::formatShipcloudEvent($latestEvent, '<br/>');

                        $xttr = new xt_tracking();
                        $statusCode = self::getXtStatusCodeFromShipcloudStatus($latestEvent->status);
                        // we need a correct shipperId for shipclud because it was mixed with shipcloud-dhl ... on insert tracking
                        $shipperId = $db->GetOne("SELECT ".COL_SHIPPER_ID_PK. " FROM ".TABLE_SHIPPER. " WHERE ".COL_SHIPPER_CODE."='shipcloud'");
                        $xttr->setStatus($tracking[0]['tracking_code'], $statusCode, $shipperId);

                        break;
                }
            }
        }
        catch (Exception $e)
        {
            $r->errorMsg = $e->getMessage();
            $r->msg = $e->getMessage();
            return json_encode($r);
        }

        $r->success = true;
        return json_encode($r);

    }


    public function updateStatusForOrder($xt_orders_id)
    {
        $r = new stdClass();
        $r->success = false;
        $r->msg = false;
        $r->errorMsg = false;

        $trackings = tracking::getTrackingForOrder($xt_orders_id);
        $hasShipcloud = false;
        foreach($trackings as $t)
        {
            if(strpos($t['shipper_code'],'shipcloud') === 0)
            {
                $hasShipcloud = true; continue;
            }
        }

        if($hasShipcloud)
        {
            $rShipcloud =  $this->updateStatusForOrderShipcloud($xt_orders_id);
        }

        $r->success = $rShipcloud->success;
        if(!$r->success)
        {
            $r->errorMsg = $r->msg = $rShipcloud->errorMsg;
        }
        else {
            $r->msg = 'OK';
        }


        return json_encode($r);

    }

    public function updateStatusForOrderShipcloud($xt_orders_id)
    {
        global $db, $store_handler;

        $r = new stdClass();
        $r->success = false;
        $r->msg = false;
        $r->errorMsg = false;

        try {
                $refNo = $store_handler->domain.'#'.$xt_orders_id;

                $responseFilter = shipcloud_api::getInstance(XT_SHIPCLOUD_API_KEY)
                ->shipmentIndex(false,false, array('reference_number' => $refNo));

                foreach($responseFilter as $resp)
                {
                    $packages = $resp->packages();
                    $latestEvent = $packages[0]->tracking_events[0];
                    foreach($packages[0]->tracking_events as $te)
                    {
                        $dtLatest = new DateTime($latestEvent->timestamp);
                        $dtCurrent = new DateTime($te->timestamp);
                        if($dtCurrent > $dtLatest)
                        {
                            $latestEvent = $te;
                        }
                    }

                    $xttr = new xt_tracking();
                    $statusCode = self::getXtStatusCodeFromShipcloudStatus($latestEvent->status);
                    // we need a correct shipperId for shipclud because it was mixed with shipcloud-dhl ... on insert tracking
                    $shipperId = $db->GetOne("SELECT ".COL_SHIPPER_ID_PK. " FROM ".TABLE_SHIPPER. " WHERE ".COL_SHIPPER_CODE."='shipcloud'");
                    $xttr->setStatus($resp->id(), $statusCode, $shipperId);
                }

                $r->msg = __define('TEXT_SUCCESS');
        }
        catch (Exception $e)
        {
            $r->errorMsg = $e->getMessage();
            $r->msg = $e->getMessage();
            return $r;
        }

        $r->success = true;
        return $r;

    }

    public function printLabel($data)
    {
        global $db;
        $r = TEXT_FAILURE;
        try {

            $tracking = tracking::getTrackingForOrder($data['orders_id'],$data['tracking_code'], false);

            if($tracking[0])
            {
                $shipper_code = $tracking[0]['shipper_code'];
                if(strpos($shipper_code, 'shipcloud-') === 0)
                {
                    $shipper_code = 'shipcloud';
                }
                switch($shipper_code)
                {
                    case 'shipcloud':
                        $labelUrl =$db->GetOne("SELECT ".COL_SHIPCLOUD_LABEL_LABEL_URL." FROM ".TABLE_SHIPCLOUD_LABELS." WHERE ".COL_SHIPCLOUD_LABEL_ID."=?", array($tracking[0]['tracking_code']));
                        header("Location: ".$labelUrl);
                        die();

                        break;
                }
            }



        }
        catch (Exception $e)
        {
            $r->errorMsg = $e->getMessage();
            $r->msg = $e->getMessage();
            return $r;
        }

        exit;

    }
    /**
     *    SHIPCLOUD
     */


    public function quotesGet_shipcloud($reqData)
    {
        global $price;

        $r = new stdClass();
        $r->success = true;
        $r->msg = 'OK';

        try
        {
            $a = shipcloud_api::getInstance(XT_SHIPCLOUD_API_KEY)
                ->quotesGet($reqData);

            $r->price = $price->_StyleFormat($a->price());
        }
        catch (Exception $e)
        {
            $r->success = false;
            $msg = explode('|', $e->getMessage());
            $msg[0] = $msg[0] . '::' . $msg[1];
            unset($msg[1]);
            $r->msg = implode("<br/>", $msg);
        }

        return json_encode($r);
    }

        /**
     * @param $data  data from $_REQUEST
     * @param bool|true $cascadeTracking
     * @return mixed|string
     */
    public function saveOrder_shipcloud($data, $order = false)
    {
        global $store_handler, $price, $db;

        xt_shipcloud_settings::readSettings();

        $pickup = false;
        try
        {
            if ($data['orders_id'] == 0)
            {
                $r = new stdClass();
                $r->success = false;
                $r->msg = 'OK';
                $order_ids = explode(',', $data['order_ids']);
                $tmp_msg = '';
                foreach ($order_ids as $order_id)
                {
                    $o = new order($order_id, -1);
                    //$delivery_addr = $aoe->getOrderData()['order_data']['delivery'];

                    if (empty($data['to_street_no']))
                    {
                        $addr_street = self::splitAddress($o->order_data['delivery_street_address'], self::getSplit());
                    }

                    $data['orders_id'] = $order_id;
                    $data['shop_id'] = $o->order_data['shop_id'];

                    $data['to_first_name'] = $o->order_data['delivery_firstname'];
                    $data['to_last_name'] = $o->order_data['delivery_lastname'];
                    $data['to_company'] = $o->order_data['delivery_company'];
                    $data['to_care_of'] = '';
                    $data['to_street'] = $o->order_data['delivery_street_address'];
                    $data['to_street_no'] = '';
                    $data['to_zip_code'] = $o->order_data['delivery_postcode'];
                    $data['to_city'] = $o->order_data['delivery_city'];
                    $data['to_state'] = $o->order_data['delivery_federal_state_code'];
                    $data['to_country'] = $o->order_data['delivery_country_code'];
                    $data['to_phone'] = $o->order_data['delivery_mobile_phone'] ? $o->order_data['delivery_mobile_phone'] : $o->order_data['delivery_phone'];
                    $data['to_email'] = $o->order_data['customers_email_address'];

                    $r_tmp = $this->saveOrder_shipcloud($data, $o);
                    if ($data['quote'] == 1)
                    {
                        return $r_tmp;
                    }
                    $r_tmp = json_decode($r_tmp);
                    $tmp_msg .= TEXT_SHIPCLOUD_ORDER . '&nbsp;' . $order_id . ':&nbsp;';
                    if ($r_tmp->success == false)
                    {
                        $tmp_msg .= $r_tmp->msg;
                    }
                    else
                    {
                        $tmp_msg .= 'OK';
                    }
                    $tmp_msg .= '<br />';
                }
                if ($r->success == false)
                {
                    $r->msg = $tmp_msg;
                }
                return json_encode($r);
            }

            $r = new stdClass();
            $r->success = true;
            $r->msg = 'OK';

            if (empty($data['to_street_no']))
            {
                $addr_street = self::splitAddress($data['to_street'], self::getSplit());
            }
            else
            {
                $addr_street = array($data['to_street'], $data['to_street_no']);
            }

            if ($order == false)
            {
                $order = new order($data['orders_id'], -1);
                $r->refresh = true;
            }
            $store_name = $db->GetOne("SELECT shop_ssl_domain FROM " . TABLE_MANDANT_CONFIG . " where shop_id = ?", array((int)$data['shop_id']));
            $reference = $data['orders_id'].'#' . $data['orders_id'];
;
            $reference_cod = $store_name . ' - ' . TEXT_SHIPCLOUD_ORDER . ' ' . $data['orders_id'];

            if (
                (($data['shipcloud_carrier'] == 'ups' && $data['shipcloud_service'] == 'returns') ||
                    ($data['shipcloud_carrier'] == 'dhl' && $data['shipcloud_service'] == 'on_day'))
                && empty($data['description'])
            )
            {
                $p_names = array();
                foreach ($order->order_products as $k => $v)
                {
                    $p_names[] = $v['products_name'];
                }
                $desc = implode('|', $p_names);
            }
            else
            {
                $desc = $data['description'];
            }

            $to = Shipcloud\Address::create()
                ->setFirstName($data['to_first_name'])
                ->setLastName($data['to_last_name'])
                ->setCareOf($data['to_care_of'])
                ->setCompany($data['to_company'])
                ->setStreet($addr_street[0])
                ->setStreetNo($addr_street[1])
                ->setCity($data['to_city'])
                ->setZipCode($data['to_zip_code'])
                ->setCountry($data['to_country'])
                ->setPhone($data['to_phone'])
                ->setCareOf($data['to_care_of']);
            if(!empty($data['to_state']))
            {
                $to->setState($data['to_state']);
            }
            $package = Shipcloud\Package::create()
                ->setLength(str_replace(',', '.', $data['package_length']))
                ->setWidth(str_replace(',', '.', $data['package_width']))
                ->setHeight(str_replace(',', '.', $data['package_height']))
                ->setWeight(str_replace(',', '.', $data['package_weight']))
                ->setType($data['shipcloud_package_type'])->setDescription($desc);

            $reqData = Shipcloud\ShipmentCreateRequest::create()
                ->setCarrier($data['shipcloud_carrier'])
                ->setService($data['shipcloud_service']);

            // check for additional services
            switch ($data['shipcloud_carrier'])
            {
                case 'dhl':
                    if ($data['add_service_dhl'] == 'on')
                    {
                        $email = trim($data['add_service_dhl_advance_notice_email']);
                        if (!empty($email))
                        {
                            $reqData->addAdditonalService(Shipcloud\AdvanceNoticeEmail::create()
                                ->setEmail($email)
                                ->setLang($order->order_data['language_code']));
                        }
                        $amount = trim($data['add_service_dhl_cash_on_delivery']);
                        $amount = doubleval(abs(str_replace(',', '.', $amount)));
                        if ($amount)
                        {
                            $reqData->addAdditonalService(Shipcloud\CashOnDelivery::create()
                                ->setAmount($amount)
                                ->setBankAccountHolder(XT_SHIPCLOUD_BANK_ACCOUNT_HOLDER)
                                ->setBankAccountNumber(XT_SHIPCLOUD_BANK_ACCOUNT_NUMBER)
                                ->setBankCode(XT_SHIPCLOUD_BANK_CODE)
                                ->setBankName(XT_SHIPCLOUD_BANK_NAME)
                                ->setCurrency($order->order_data['currency_code'])
                                ->setReference1($reference_cod));
                        }
                        $declared_value = floatval(trim($data['add_service_dhl_declared_value']));
                        $declared_value = doubleval(abs(str_replace(',', '.', $declared_value)));
                        if ($declared_value)
                        {
                            $package->setDeclaredValue(Shipcloud\DeclaredValue::create()
                                ->setAmount($declared_value)
                                ->setCurrency($order->order_data['currency_code']));
                        }
                    }
                    break;
                case 'dpd':
                    if ($data['add_service_dpd'] == 'on')
                    {
                        $email = trim($data['add_service_dpd_advance_notice_email']);
                        if (!empty($email))
                        {
                            $reqData->addAdditonalService(Shipcloud\AdvanceNoticeEmail::create()
                                ->setEmail($email)
                                ->setLang($order->order_data['language_code']));
                        }
                        $sms = trim($data['add_service_dpd_advance_notice_sms']);
                        $sms = preg_replace('/[0-9]/', '', $sms);
                        if (!empty($sms))
                        {
                            $reqData->addAdditonalService(Shipcloud\AdvanceNoticeSms::create()
                                ->setSms('+' . $sms));
                        }
                        $msg = trim($data['add_service_dpd_drop_authorization_msg']);
                        if (!empty($msg))
                        {
                            $reqData->addAdditonalService(Shipcloud\DropAuthorization::create()
                                ->setMessage($msg));
                        }
                        if ($data['add_service_dpd_saturday_delivery'] == 'on')
                        {
                            $reqData->addAdditonalService(Shipcloud\SaturdayDelivery::create());
                        }
                    }
                    break;
            }

            $reqData->setPackage($package);

            $from = Shipcloud\Address::create();
            if (XT_SHIPCLOUD_DIFFERENT_RETOURE === "1" && $data['shipcloud_service'] == 'returns')
            {
                $from->setFirstName($data['retoure_first_name'])
                    ->setLastName($data['retoure_last_name'])
                    ->setCompany($data['retoure_company'])
                    ->setStreet($data['retoure_street'])
                    ->setStreetNo($data['retoure_street_no'])
                    ->setCity($data['retoure_city'])
                    ->setZipCode($data['retoure_zip_code'])
                    ->setCountry($data['retoure_country'])->setPhone($data['retoure_phone']);
                if(!empty($data['retoure_state']))
                {
                    $from->setState($data['retoure_state']);
                }
            }
            else
            {
                $from->setFirstName($data['from_first_name'])
                    ->setLastName($data['from_last_name'])
                    ->setCompany($data['from_company'])
                    ->setStreet($data['from_street'])
                    ->setStreetNo($data['from_street_no'])
                    ->setCity($data['from_city'])
                    ->setZipCode($data['from_zip_code'])
                    ->setCountry($data['from_country'])->setPhone($data['from_phone']);
                if(!empty($data['from_state']))
                {
                    $from->setState($data['from_state']);
                }
            }

            if ($data['shipcloud_service'] == 'returns')
            {
                $tmp = $from;
                $from = $to;
                $to = $tmp;
            }

            $reqData->setFrom($from)->setTo($to);

            // pickup
            $pickup = null;
            if ($data['pickup'] == 1 || $data['pickup'] == 'on' || $data['shipcloud_carrier'] == 'go')
            {
                switch ($data['shipcloud_carrier'])
                {
                    case 'dhl_express':
                    case 'go':
                        $data['pickup_latest_date'] = $data['pickup_earliest_date'];
                        $data['pickup_latest_time'] = $data['pickup_earliest_time'];
                        break;
                    default:

                }
                $earliestDateTime = DateTime::createFromFormat('d.m.Y H:i', $data['pickup_earliest_date'] . ' ' . $data['pickup_earliest_time']);
                $latestDateTime = DateTime::createFromFormat('d.m.Y H:i', $data['pickup_latest_date'] . ' ' . $data['pickup_latest_time']);
                $pickupTime = new stdClass();
                $pickupTime->earliest = $earliestDateTime->format(DATE_ATOM);
                $pickupTime->latest = $latestDateTime->format(DATE_ATOM);
                $pickup = new \Shipcloud\Pickup();
                $pickup->setCarrier($data['shipcloud_carrier'])
                    ->setPickupAddress($from)
                    ->setPickupTime($pickupTime);
            }

            if ($data['quote'] == 1)
            {
                return $this->quotesGet_shipcloud($reqData);
            }
        }
        catch(Exception $e)
        {
            $r->success = false;
            $msg =  $e->getMessage();
            $r->msg = $msg;
        }

        try
        {
            $reqData->setDescription($desc)
                ->setReferenceNumber($reference)
                ->setNotificationEmail($data['to_email'])
                ->setCreateShippingLabel(true)
                ->setLabel( Shipcloud\Label::create()->setSize('A5'));
            if($pickup)
            {
                $reqData->setPickup($pickup);
            }
            if($data['prepare_label'] == 1)
            {
                $reqData->setCreateShippingLabel(false);
            }

            $log_file = _SRV_WEBROOT._SRV_WEB_LOG."shipcloud_io.log";
            $aff_id = 'integration.xtcommerce.B7HjJWzu';

            $responseCreate = shipcloud_api::getInstance(XT_SHIPCLOUD_API_KEY, $aff_id, $log_file)
                ->shipmentCreate($reqData);
            $dateCreated = new DateTime();

            $r->price = $price->_StyleFormat($responseCreate->price());

            /*
            $responseRead = shipcloud_api::getInstance(XT_SHIPCLOUD_API_KEY)
                ->shipmentRead($responseCreate->id());


            $arr = array(
                COL_SHIPCLOUD_XT_ORDER_ID => $data['orders_id'],
                COL_SHIPCLOUD_LABEL_CARRIER => $responseRead->carrier(),
                COL_SHIPCLOUD_LABEL_CARRIER_TRACKING_NO => $responseRead->carrierTrackingNo(),
                COL_SHIPCLOUD_LABEL_CREATED_AT => $responseRead->createdAt(),
                COL_SHIPCLOUD_LABEL_FROM => serialize($responseRead->from()),
                COL_SHIPCLOUD_LABEL_ID => $responseRead->id(),
                COL_SHIPCLOUD_LABEL_LABEL_URL => $responseRead->labelUrl(),
                COL_SHIPCLOUD_LABEL_NOTIFICATION_EMAIL => $responseRead->notificationEmail(),
                COL_SHIPCLOUD_LABEL_PACKAGES => serialize($responseRead->packages()),
                COL_SHIPCLOUD_LABEL_PRICE => $responseRead->price(),
                COL_SHIPCLOUD_LABEL_REFERENCE_NUMBER => $responseRead->referenceNumber(),
                COL_SHIPCLOUD_LABEL_SERVICE => $responseRead->service(),
                COL_SHIPCLOUD_LABEL_SHIPPER_NOTIFICATION_EMAIL => $responseRead->shipperNotificationEmail(),
                COL_SHIPCLOUD_LABEL_TO =>  serialize($responseRead->to()),
                COL_SHIPCLOUD_LABEL_TRACKING_URL => $responseRead->trackingUrl()

            );
            */
            $arr = array(
                COL_SHIPCLOUD_XT_ORDER_ID => $data['orders_id'],
                COL_SHIPCLOUD_LABEL_CARRIER => $data['shipcloud_carrier'],
                COL_SHIPCLOUD_LABEL_CARRIER_TRACKING_NO => $responseCreate->carrierTrackingNo(),
                COL_SHIPCLOUD_LABEL_CREATED_AT => $dateCreated->format("Y-m-d H:i:s"),
                COL_SHIPCLOUD_LABEL_FROM => serialize($from),
                COL_SHIPCLOUD_LABEL_ID => $responseCreate->id(),
                COL_SHIPCLOUD_LABEL_LABEL_URL => $responseCreate->labelUrl(),
                COL_SHIPCLOUD_LABEL_NOTIFICATION_EMAIL => $data['to_email'],
                COL_SHIPCLOUD_LABEL_PACKAGES => serialize($package),
                COL_SHIPCLOUD_LABEL_PRICE => $responseCreate->price(),
                COL_SHIPCLOUD_LABEL_REFERENCE_NUMBER => $reference,
                COL_SHIPCLOUD_LABEL_SERVICE => $data['shipcloud_service'],
                COL_SHIPCLOUD_LABEL_SHIPPER_NOTIFICATION_EMAIL => '', // TODO ?
                COL_SHIPCLOUD_LABEL_TO =>  serialize($to),
                COL_SHIPCLOUD_LABEL_TRACKING_URL => $responseCreate->trackingUrl(),
                COL_SHIPCLOUD_LABEL_PICKUP => serialize($pickup)

            );
            $sats = new xt_ship_and_track_shipcloud();
            $sats->_set($arr, 'new');

            global $db;
            $shipperId = $db->GetOne(" SELECT `".COL_SHIPPER_ID_PK."` FROM ". TABLE_SHIPPER ." WHERE `".COL_SHIPPER_CODE."`=? ", array('shipcloud-'.$data['shipcloud_carrier']));
            if(!$shipperId)
            {
                $shipperCode =  'shipcloud-'.$data['shipcloud_carrier'];
                $inserData = array(
                    COL_SHIPPER_CODE => $shipperCode,
                    COL_SHIPPER_NAME => $shipperCode,
                    COL_SHIPPER_TRACKING_URL => 'https://track.shipcloud.io/[TRACKING_CODE]',
                );
                $inserData[COL_SHIPPER_API_ENABLED] = 1;

                try {
                    $db->AutoExecute(TABLE_SHIPPER ,$inserData);
                } catch (exception $e) {
                    return $e->msg;
                }
                $shipperId = $db->Insert_ID();
                /*
                $xts = new xt_shipper();
                $xts->_installStatusCodes($shipperId, $shipperCode, array('de'));
                */
            }

            $shipcloudShipperId = $db->GetOne("SELECT ".COL_SHIPPER_ID_PK." FROM ".TABLE_SHIPPER." WHERE ".COL_SHIPPER_CODE."='shipcloud'");
            $statusId = $db->GetOne('SELECT `'.COL_TRACKING_STATUS_ID_PK.'` FROM '.TABLE_TRACKING_STATUS.' WHERE `'.COL_TRACKING_STATUS_CODE."`=1 AND `".COL_TRACKING_SHIPPER_ID. "`=?", array($shipcloudShipperId) );
            $tracking = new xt_tracking();
            $data = array(
                'orders_id' => $data['orders_id'],
                'shipper' => $shipperId,
                'tracking_codes' => $responseCreate->id(),
                'send_email' => false,
                'status' => $statusId
            );
            $tracking->addTracking($data, false);
            //$tracking->setStatus(substr($responseRead->id(), 0, 10), 1);

            /**
            COL_SHIPCLOUD_XT_ORDER_ID
            COL_SHIPCLOUD_LABEL_CARRIER
            COL_SHIPCLOUD_LABEL_CARRIER_TRACKING_NO
            COL_SHIPCLOUD_LABEL_CREATED_AT
            COL_SHIPCLOUD_LABEL_FROM
            COL_SHIPCLOUD_LABEL_ID
            COL_SHIPCLOUD_LABEL_LABEL_URL
            COL_SHIPCLOUD_LABEL_NOTIFICATION_EMAIL
            COL_SHIPCLOUD_LABEL_PACKAGES
            COL_SHIPCLOUD_LABEL_PRICE
            COL_SHIPCLOUD_LABEL_REFERENCE_NUMBER
            COL_SHIPCLOUD_LABEL_SERVICE
            COL_SHIPCLOUD_LABEL_SHIPPER_NOTIFICATION_EMAIL
            COL_SHIPCLOUD_LABEL_TO
            COL_SHIPCLOUD_LABEL_TRACKING_URL
             */
        }
        catch(Exception $e)
        {
            $r->success = false;
            $msg = explode('|', $e->getMessage());
            $msg[0] = $msg[0].'::'.$msg[1];
            unset($msg[1]);
            $r->msg = implode("<br/>", $msg);
        }

        return json_encode($r);
    }



    /**
     *
     * @return array die verfügbaren store names für DropdownData
     */
    public static function getStores()
    {
        $data = array();

        global $store_handler;
        $_data = $store_handler->getStores();

        foreach ($_data as $sdata) {
            $data[] =  array('id' => $sdata['id'],
                'name' => $sdata['text']);
        }

        return $data;
    }

    /**
     * Split a string into an array consisting of Street, House Number and
     * House extension.
     *
     * @param string $address Address string to split
     *
     * @return array
     */
    public static function splitAddress($address)
    {
        /**
         *  ok, wir versuchen also aus irgend'ner zeile eine strasse, hausnummer und extension zu ermitteln ...
         *  alle begriffe daher in anführungszeichen ...
         */

        $address = trim($address);
        // ist die 'hausnummer' vorne...
        $hasMatchStart = preg_match('/^[0-9]+/', $address, $match);
        $hasMatchEnd = 0;
        if($hasMatchStart == 0)
        {
            // ... oder hinten
            $hasMatchEnd = preg_match('/[0-9]+.*$/', $address, $match);
            // aber nicht in der mitte
            $startsWithString = preg_match('/[0-9]+.*$/', $address, $match2);
            if($startsWithString)
                $hasMatchEnd = 1;
        }

        // weder noch, zurück mit eingabe
        if (!$hasMatchEnd && !$hasMatchStart) {
            return array($address, "", "");
        }

        if($hasMatchStart)
        {
        $addrArray = explode(" ", $address);

            // wenn vorne, ist 1stes element unsere 'hausnummer'
            $housenumber = trim($addrArray[0]);

            // den rest sehen wir als 'strasse'
            $street = trim(str_replace($housenumber, "", $address));

            // addressAddition lässt sich hier nicht sinnvoll ermitteln
            return array($street, $housenumber, '');
        }
        else {
            // 'hausnummer'
            $housenumber = trim($match[0]);

            // strasse
            $street = trim(str_replace($housenumber, "", $address));

            // hängt da noch eine extension an der hausnummer dran? puh
            $addrArray = explode(" ", $housenumber);
            if(count($addrArray)>1)
            {
                unset($addrArray[0]);
                $extension = trim(implode(" ", $addrArray));
                $housenumber = trim(str_replace($extension, "", $housenumber));
            }
            else {
                $extension = '';
            }

        return array($street, $housenumber, $extension);
    }
    }

    public static function getSplit($country = false)
    {
        return array('street', 'house_number', 'house_extension');
    }

    public static function formatShipcloudEvent($se, $glueLine = ' | ', $glueParam = ': ')
    {
        if(is_object($se))
        {
            $se = (array)$se;
        }
        $ts = new DateTime($se['timestamp']);
        $msgData = array(
            'Zeitstempel'.$glueParam . $ts->format('Y-m-d H:i:s'),
            'Ort'.$glueParam . $se['location'],
            'Details'.$glueParam . $se['details']
        );
        return implode($glueLine, $msgData);
    }

    public static function getXtStatusCodeFromShipcloudStatus($status = 'unknown')
    {
        $map = array(
           'label_created' => 1,
            'picked_up' => 2,
            'transit' => 3,
            'out_for_delivery' => 4,
            'delivered' => 5,
            'awaits_pickup_by_receiver' => 7,
            'canceled' => 8,
            'delayed' => 9,
            'exception' => 10,
            'not_delivered' => 11,
            'notification' => 12,
            'destroyed' => 13,
            'unknown'   => 14
        );
        if(array_key_exists($status, $map))
        {
            return $map[$status];
        }
        else return $map['unknown'];
    }

}