<?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.

// Following our style guide, each class/interface definition must be part of a namespace and hence that rule must be
// disabled for this file!
// phpcs:disable PSR1.Classes.ClassDeclaration.MissingNamespace

/**
 * This interface defines all methods that are required to act as a shipping provider for Pickware.
 * That is, handling the shipping of orders, based on their dispatch method as well as providing
 * shipping labels for these orders.
 */
// Following our style guide, classes/interfaces must use CamelCase names and hence the next line must be ignored!
// phpcs:ignore Squiz.Classes.ValidClassName.NotCamelCaps
interface ViisonPickwareMobile_Interfaces_ShippingProvider_ShippingProvider
{
    /**
     * Returns the identifier of this provider, which can be used to e.g. map providers by type.
     *
     * @return string
     */
    public function getIdentifier();

    /**
     * Returns the name of this provider, which can be used e.g. in the frontend.
     *
     * @return string The name of this provider.
     */
    public function getName();

    /**
     * Creates a new shipping label for the order with the given id and returns an instance of
     * a class implementing the ViisonPickwareMobile_Interfaces_ShippingLabelCreationResult interface.
     *
     * @param int $orderId The id of the order, for which a new shipping label shall be created.
     * @param int|string|null $shippingProductIdentifier The identifier of the shipping product, which shall be used for the label.
     * @param float $weight The weight of the package, for which the label shall be created.
     * @param array $dimensions An array containing length, width and height of the package, for which the label shall be created.
     * @param array $options An array containing options, which can be applied on the selected shipping product.
     * @param array $exportDocumentItems An optional array containing the ids and quantities of all items,
     *        which shall be included in the possibly created export document.
     * @param array $address An optional array containing the address that shall be used as the destination of the label.
     * @return ViisonPickwareMobile_Interfaces_ShippingProvider_ShippingLabelCreationResult An instance of a ShippingLabelCreationResult implementation.
     * @throws \Exception If the label couldn't be created.
     */
    public function addLabelToOrder($orderId, $shippingProductIdentifier = null, $weight = null, $dimensions = null, $options = [], $exportDocumentItems = null, $address = null);

    /**
     * Gets the actual document file with the given identifier and returns it.
     *
     * @param int $orderId The id of the order, for which the document shall be fetched.
     * @param string $identifier The identifier of the document.
     * @return string The raw document contained in a byte buffer.
     * @throws Exception, if creating or downloading the document failed.
     */
    public function getDocument($orderId, $identifier);

    /**
     * Gathers all the documents (labels, export documents etc.) of the order with the given id
     * and returns an instance of a class, implementing the ViisonPickwareMobile_Interfaces_ShippingDocument interface,
     * for each of those documents, all wrapped in one array.
     *
     * @param int $orderId The of the order, whose documents shall be returned.
     * @param boolean $undispatchedOnly An optional boolean, indicating that only the document of those labels shall be returned, which are not yet dispatched.
     * @return ViisonPickwareMobile_Interfaces_ShippingProvider_ShippingDocument[] An array containing all gathered documents, which are all instances of a ShippingDocument implementation.
     */
    public function getAllDocumentDescriptions($orderId, $undispatchedOnly = false);

    /**
     * Checks if the shipping document with the given identifier has been created
     * by the implementing shipping provider.
     *
     * @param string $identifier The identifier of the document.
     * @return boolean True, if the implementing shipping provider has created the document with the given identifier. Otherwise false.
     */
    public function hasCreatedDocumentWithIdentifier($identifier);

    /**
     * Checks if the given tracking code has been created by the implementing shipping provider.
     *
     * @param string $trackingCode The tracking code to check.
     * @return boolean True, if the implementing shipping provider has created the tracking code. Otherwise false.
     */
    public function hasCreatedTrackingCode($trackingCode);

    /**
     * Returns the ID of the order the given tracking code is associated with.
     *
     * @param string $trackingCode The tracking code to check.
     * @return int|null
     */
    public function getOrderIdForTrackingCode($trackingCode);

    /**
     * Returns the IDs of all orders that are associated with a shipping label, whose tracking code
     * contains or matches the given tracking code fragment.
     *
     * @param string $trackingCodeFragment The fragment of a tracking code to match.
     * @return int[]
     */
    public function getOrdersIdsForTrackingCodeFragment($trackingCodeFragment);

    /**
     * Determines whether the order with the given id is supported in the implementing shipping provider.
     * That is, shipping will be supported, if the shipping method, respectively the assigned shipping product,
     * matches one of the products of the implementing provider.
     *
     * @param int $orderId The id of the order, whose shipping support in the implementing provider shall be tested.
     * @return boolean True, if the implementing shipping provider supports the order with the given id, otherwise false.
     */
    public function isShippingSupported($orderId);

    /**
     * First checks if the shipment weight calculation is activated in the configuration of the implementing plugin
     * and returns the configured default weight if not. Otherwise calculates the weight of a shipment
     * containing all items of the order with the given id. That is, the weight of all items multiplied
     * with their quantities is summed up and multiplied with the factor for filling material.
     * Finally the fixed surcharge for other packaging material is added and the total weight
     * in kilograms is returned.
     *
     * @param int $orderId The id of the order whose package weight should be calculated.
     * @param array $orderDetails An optional array containing the ids and quantities of all order detail items,
     *        whose weight multiplied with the quantity shall be included in the calculated weight.
     * @return float The calculated package weight or 0, if the order doesn't contain any items whose weight is set.
     */
    public function determineShipmentWeight($orderId, $orderDetails = null);

    /**
     * Determines whether in order to create shipping labels for the order with the given id
     * the package dimensions (length, width and height) are required.
     *
     * @param int $orderId The id of the order, for which the requirements shall be checked.
     * @return boolean True, if the package dimensions are required. Otherwise false.
     */
    public function packageDimensionsRequired($orderId);

    /**
     * Gathers all dispatch ids, which are possibly supported by this shipping provider
     * and returns them in an array.
     *
     * @return array An array containing all gathered dispatch ids.
     */
    public function validDispatchIds();

    /**
     * Gathers all shipping products, which are offered by this provider and returns them in an array.
     * Each entry is an instance of ViisonPickwareMobile_Interfaces_ShippingProduct.
     *
     * @return array An array of ViisonPickwareMobile_Interfaces_ShippingProduct instances.
     */
    public function shippingProducts();

    /**
     * Looks up the shipping product for the order with the given id and returns its identifier.
     *
     * @param int $orderId The id of the order, whose shipping product's identifier shall be returned.
     * @return string The product identifier.
     */
    public function shippingProductIdentifierForOrder($orderId);

    /**
     * Returns an array of key/value pairs for options, which should be applied
     * on the shipping product of this order.
     *
     * @param int $orderId The id of the order, whose required shipping product's options shall be returned.
     * @return array An array containing key/value pairs for the required shipping product options.
     */
    public function shippingProductOptionsForOrder($orderId);

    /**
     * Returns the status URLs, which can be used to track all shipping labels, whose
     * tracking codes are passed to this method.
     *
     * TODO: This Method is commented out to make this interface definition compatible with old versions of shipping
     * provider plugins. Once all shipping provider plugins have adopted the new interface for some time, we can enable
     * the method definition.
     *
     * @param string[] $trackingCodes An array containing the tracking codes, which shall be contained in the status URL.
     * @return string[] The status URLs.
     */
    // public function statusUrlsForTrackingCodes($trackingCodes);

    /**
     * TODO: This Method is commented out to make this interface definition compatible with old versions of shipping
     * provider plugins. Once all shipping provider plugins have adopted the new interface for some time, we can enable
     * the method definition.
     *
     * @return ViisonPickwareMobile_Interfaces_ShippingProvider_ShippingDocumentType[]
     */
    // public function getAvailableShippingDocumentTypes();
}
