<?php
namespace Shopware\Plugins\ViisonDHL\Classes\DhlServiceOptions;

use DateTime;
use Shopware\Models\Attribute\Order as OrderAttributes;
use Shopware\Plugins\ViisonDHL\Classes\DHLException;
use Shopware\Plugins\ViisonDHL\Classes\SoapRequestBodyMutator;

class PreferredDeliveryServiceOption implements SoapRequestBodyMutator
{
    const MAX_PREFERRED_NEIGHBOUR_LENGTH = 100;
    const MAX_PREFERRED_LOCATION_LENGTH = 100;

    /**
     * @var string
     */
    private $preferredLocation;

    /**
     * @var string
     */
    private $preferredDayOfDelivery;

    /**
     * @var string
     */
    private $preferredNeighbour;

    /**
     * @param array $requestBody
     * @return array
     */
    public function mutate(array $requestBody)
    {
        // The DHL Webservice complains for some values for the preferred delivery if they are null or a empty string,
        // because of that we are checking all values.
        if ($this->preferredNeighbour) {
            $requestBody['ShipmentOrder']['Shipment']['ShipmentDetails']['Service']['PreferredNeighbour'] = [
                'active' => 1,
                'details' => mb_substr(
                    $this->preferredNeighbour,
                    0,
                    self::MAX_PREFERRED_NEIGHBOUR_LENGTH,
                    'utf-8'
                ),
            ];
        }

        if ($this->preferredLocation) {
            $requestBody['ShipmentOrder']['Shipment']['ShipmentDetails']['Service']['PreferredLocation'] = [
                'active' => 1,
                'details' => mb_substr(
                    $this->preferredLocation,
                    0,
                    self::MAX_PREFERRED_NEIGHBOUR_LENGTH,
                    'utf-8'
                ),
            ];
        }

        if ($this->preferredDayOfDelivery) {
            $requestBody['ShipmentOrder']['Shipment']['ShipmentDetails']['Service']['PreferredDay'] = [
                'active' => 1,
                'details' => $this->preferredDayOfDelivery,
            ];
        }

        return $requestBody;
    }

    /**
     * @param array $extraSettings
     * @return PreferredDeliveryServiceOption
     * @throws DHLException
     */
    public static function createFromExtraSettings(array $extraSettings)
    {
        $preferredDeliveryServiceOption = new self();

        $preferredDeliveryServiceOption->preferredDayOfDelivery = $extraSettings['preferredDayOfDelivery'];
        $preferredDeliveryServiceOption->preferredLocation = $extraSettings['preferredLocation'];
        $preferredDeliveryServiceOption->preferredNeighbour = $extraSettings['preferredNeighbour'];

        if ($preferredDeliveryServiceOption->preferredLocation && $preferredDeliveryServiceOption->preferredNeighbour) {
            throw DHLException::preferredNeighbourAndLocationSetTogether();
        }

        return $preferredDeliveryServiceOption;
    }

    /**
     * @param OrderAttributes $orderAttributes
     * @return PreferredDeliveryServiceOption
     * @throws DHLException
     */
    public static function createFromOrderAttributes(OrderAttributes $orderAttributes)
    {
        $preferredDeliveryServiceOption = new self();

        // DHl supports only one field, but DHL Wunschpaket has two separate fields.
        $preferredNeighbour = implode(
            ';',
            array_filter(
                [
                    $orderAttributes->getMoptwunschpaketpreferredneighborname(),
                    $orderAttributes->getMoptwunschpaketpreferredneighboraddress(),
                ]
            )
        );

        $preferredDeliveryServiceOption->preferredNeighbour = $preferredNeighbour;
        $preferredDeliveryServiceOption->preferredLocation = $orderAttributes->getMoptwunschpaketpreferredlocation();

        if ($orderAttributes->getMoptwunschpaketpreferredday()) {
            $preferredDeliveryServiceOption->preferredDayOfDelivery = DateTime::createFromFormat(
                'd.m.Y',
                $orderAttributes->getMoptwunschpaketpreferredday()
            )->format('Y-m-d');
        }

        if ($preferredDeliveryServiceOption->preferredLocation && $preferredDeliveryServiceOption->preferredNeighbour) {
            throw DHLException::preferredNeighbourAndLocationSetTogether();
        }

        return $preferredDeliveryServiceOption;
    }
}
