<?php
// Copyright (c) Pickware GmbH. All rights reserved.
// This file is part of software that is released under a proprietary license.
// You must not copy, modify, distribute, make publicly available, or execute
// its contents or parts thereof without express permission by the copyright
// holder, unless otherwise permitted by law.

namespace Shopware\Plugins\ViisonDHL;

use Shopware\Plugins\ViisonShippingCommon\Util as ShippingCommonUtil;
use Shopware\Plugins\ViisonDHL\Classes\PluginInfo;

/**
 * Contains utility methods and values which are used by several classes of the ViisonDHL plugin.
 */
class Util extends ShippingCommonUtil
{
    const MOB_DOCTRINE_GET_ADDRESS_TYPE = 'getMoptwunschpaketaddresstype';

    /**
     * DHL test user credentials
     *
     * @var string[]
     */
    protected static $testUserCredentials = [
        'username' => '2222222222_01',
        'password' => 'pass',
        'ekp' => '2222222222',
    ];

    /**
     * Returns the string to be used for password encryption.
     *
     * @override
     * @return string
     */
    protected function getKey()
    {
        return null;
    }

    /**
     * Returns an array containing all config fields that are always needed for label creation.
     *
     * @override
     * @return array
     */
    protected function getMandatoryConfigFields()
    {
        return [
            'senderName',
            'streetName',
            'streetNumber',
            'zipCode',
            'city',
            'phoneNumber',
            'countryiso',
        ];
    }

    /**
     * Protected constructor to prevent creating a new instance of the
     * Singleton via the `new` operator from outside of this class.
     */
    protected function __construct()
    {
        parent::__construct(new PluginInfo);
    }

    /**
     * Private clone method to prevent cloning of the instance of the
     * Singleton instance.
     *
     * @return void
     */
    private function __clone()
    {
    }

    /**
     * Private unserialize method to prevent unserializing of the Singleton
     * instance.
     *
     * @return void
     */
    public function __wakeup()
    {
    }

    public static function instance()
    {
        static $instance = null;
        if (null === $instance) {
            $instance = new static();
        }

        return $instance;
    }

    /**
     * Returns if the config contains all fields necessary to create labels for the given order.
     *
     * @override
     * @param int $orderId
     * @param array $config
     * @return bool
     */
    protected function hasOrderSpecificValidConfig($orderId, $config)
    {
        $product = self::getProduct($orderId);

        // NOTE: if productCode is "EXP' jump over because we are using the DHL Global Web Service so we
        //       don't need the check for productIdEXP
        if (!empty($product) && !empty($product['productCode']) && $product['productCode'] != 'EXP') {
            return !empty($config['partnerId' . $product['productCode']]);
        }

        return true;
    }

    /**
    * Returns an array containing the plugin specific product fields and their respective values for the given product table row.
     *
    * @override
    * @param int $shopId
    * @param array $product
    * @return array
    */
    protected function getExtraProductFields($shopId, $product)
    {
        // Get corresponding DHL partner id
        // For express shipping don't set the partnerId because we don't need it for DHL Global Web Service
        $partnerId = $product['code'] != 'EXP' ? $this->config($shopId, ('partnerId' . $product['code'])) : null;

        return [
            'partnerId' => $partnerId,
            'dateTimeOption' => $product['dateTimeOption'],
            'premiumOption' => $product['premiumOption'],
            'bulkfreightOption' => $product['bulkfreightOption'],
            'insuranceAmount' => $product['insuranceAmount'],
            'process' => $product['process'],
            'product' => $product['product'],
            'isDutiable' => (bool) $product['isDutiable'],
            'requiresEmail' => (bool) $product['requiresEmail'],
        ];
    }

    /**
     * Returns the default shipment weight for the given product.
     * @override
     * @param int $shopId
     * @param array $product
     * @return float
     */
    public function getDefaultShipmentWeight($shopId, $product)
    {
        return $this->config($shopId, 'defaultShipmentWeight' . $product['productCode']);
    }

    public function isTrackingCodeExpressShipment($trackingCode)
    {
        $stmt = Shopware()->Db()->query(
            'SELECT p.code
            FROM `' . $this->pluginInfo->getOrderTableName() . '` o
            LEFT JOIN s_viison_dhl_products p ON p.id = o.productId
            WHERE o.trackingcode LIKE ?',
            [$trackingCode]
        );

        $row = $stmt->fetch();

        if ($row === false) {
            throw new \Exception('Could not determine if shipment is an express shipment.');
        }

        $productCode = $row['code'];

        // Product code is unknown (label was created before the productId column was introduced) => treat the shipment as a non-express shipment
        if ($productCode === null) {
            return false;
        }

        return $productCode == 'EXP';
    }

    /**
     * @override
     * @param int $orderId
     */
    public function packageDimensionsRequiredForOrder($orderId)
    {
        $product = $this->getProduct($orderId);

        // Do not use package dimensions if no product mapping exists
        if ($product === null) {
            return false;
        }

        // The package dimensions have to be given for express shipments
        return $product['productCode'] == 'EXP';
    }

    /**
     * @param bool $sameDayDelivery
     */
    public function getDefaultDayOfDelivery($sameDayDelivery)
    {
        // Determine day of delivery
        $date = new \DateTime;
        // Check if product is same day delivery, use next weekday if same day delivery was not chosen
        if (!$sameDayDelivery) {
            $date->modify('+1 Weekday');
        }

        return $date;
    }

    /**
     * Get order attributes if DHL Packing station (MOB) plugin is installed
     *
     * @param $orderId
     * @return null|\Shopware\Models\Attribute\Order
     */
    public function getOrderAttributeIfPackingStationPluginExist($orderId)
    {
        if (empty($orderId)) {
            return null;
        }

        /** @var \Shopware\Models\Attribute\Order $orderAttribute */
        $orderAttribute = Shopware()->Models()->getRepository(
            'Shopware\\Models\\Attribute\\Order'
        )->findOneByOrderId(
            $orderId
        );

        return method_exists($orderAttribute, self::MOB_DOCTRINE_GET_ADDRESS_TYPE) ? $orderAttribute : null;
    }
}
