<?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\ViisonShippingCommon\Classes;

use FPDI;
use setasign\Fpdi\Fpdi as Fpdi2;
use Shopware\Models\Order\Order;
use Shopware\Plugins\ViisonCommon\Classes\Util\Util;
use Zend\Barcode\Barcode;

class BarCodeHelper
{
    /**
     * Adds a barcode image (with $order id) at a specific $position of a PDF file stored at $pdfFilePath
     *
     * The barcode has a special format that can be read by the Pickware Mobile apps
     *
     * @param $pdfFilePath
     * @param Order $order
     * @param float $positionX Position of the barcode from the left (when negative: from the right)
     * @param float $positionY Position of the barcode from the top (when negative: from the bottom)
     * @param float $width Width of the barcode
     * @param float $height Height of the barcode
     * @param int $rotationDegrees Rotation of the barcode in degrees
     * @return string The new PDF file content
     */
    public static function addOrderBarCodeToPdfFile($pdfFilePath, Order $order, $positionX, $positionY, $width, $height, $rotationDegrees = 0)
    {
        // SW 5.3 brings FPDI as a composer requirement, so it does not need to be included anymore
        if (!class_exists('FPDI')) {
            include_once('engine/Library/Fpdf/fpdf.php');
            include_once('engine/Library/Fpdf/fpdi.php');
        }

        // Generate a action barcode which will mark the order as shipped (action=1)
        $barCodeImage = self::generateOrderActionBarCodeAsPng($order, 1, $rotationDegrees);
        $barCodeImageTempFileName = Util::getTempDir() . '/shippingCommonBarcode_' . $order->getId() . '_' . uniqid();
        imagepng($barCodeImage, $barCodeImageTempFileName);

        // Shopware 5.7 ships with FPDI 2.x, use if available
        $useFpdf2 = class_exists('setasign\\Fpdi\\Fpdi');
        if ($useFpdf2) {
            $fPdf = new Fpdi2();
        } else {
            $fPdf = new FPDI();
        }
        $fPdf->setSourceFile($pdfFilePath);

        $template = $fPdf->importPage(1);
        $size = $fPdf->getTemplateSize($template);
        if ($useFpdf2) {
            $orientation = $size['orientation'];
            $sizeWidth = $size['width'];
            $sizeHeight = $size['height'];
        } else {
            $orientation = ($size['h'] > $size['w']) ? 'P' : 'L';
            $sizeWidth = $size['w'];
            $sizeHeight = $size['h'];
        }
        $fPdf->AddPage(
            $orientation,
            array(
                $sizeWidth,
                $sizeHeight,
            )
        );

        $fPdf->useTemplate($template);

        if ($positionX < 0) {
            $positionX += $sizeWidth;
        }
        if ($positionY < 0) {
            $positionY += $sizeHeight;
        }

        $fPdf->Image($barCodeImageTempFileName, $positionX, $positionY, $width, $height, 'PNG');

        unlink($barCodeImageTempFileName);

        // Return modified PDFs content
        return $fPdf->Output('', 'S');
    }

    /**
     * Adds a barcode image (with $order id) at a specific $position of a PDF
     *
     * The barcode has a special format that can be read by the Pickware Mobile apps
     *
     * @param string $pdf
     * @param Order $order
     * @param float $positionX Position of the barcode from the left (when negative: from the right)
     * @param float $positionY Position of the barcode from the top (when negative: from the bottom)
     * @param float $width Width of the barcode
     * @param float $height Height of the barcode
     * @param int $rotationDegrees Rotation of the barcode in degrees
     * @return string The new PDF file content
     * @throws \Exception
     */
    public static function addOrderBarCodeToPdf($pdf, Order $order, $positionX, $positionY, $width, $height, $rotationDegrees = 0)
    {
        $tempFilePath = Util::getTempDir() . '/shippingCommonAddOrderBarcode_' . $order->getId() . '_' . uniqid();
        $writeSuccess = file_put_contents($tempFilePath, $pdf);
        if ($writeSuccess === false) {
            $exceptionMessagesNamespace = Shopware()->Container()->get('snippets')->getNamespace(
                'backend/viison_shipping_common_exceptions/exceptions'
            );

            throw new \Exception(sprintf(
                $exceptionMessagesNamespace->get('exception/write_document'),
                $tempFilePath
            ));
        }

        try {
            $modifiedPdf = self::addOrderBarCodeToPdfFile(
                $tempFilePath,
                $order,
                $positionX,
                $positionY,
                $width,
                $height,
                $rotationDegrees
            );
        } finally {
            unlink($tempFilePath);
        }

        return $modifiedPdf;
    }

    /**
     * Create Barcode and converts it to a PNG
     *
     * @param Order $order
     * @param int $action 1=Mark order as shipped
     * @param int $rotationDegrees Rotation of the barcode in degrees
     * @return mixed
     */
    public static function generateOrderActionBarCodeAsPng(Order $order, $action, $rotationDegrees = 0)
    {
        $code = '^' . $action . $order->getId();
        // Draw a new barcode image using Zend\Barcode\Barcode
        $config = new \Zend_Config(array(
            'barcode' => 'code128',
            'barcodeParams' => array(
                'text' => $code,
                'factor' => 5,
                'barHeight' => 30,
                'withQuietZones' => false,
                'drawText' => false,
                'orientation' => $rotationDegrees
            ),
            'renderer' => 'image',
            'rendererParams' => array('imageType' => 'png')
        ));

        return Barcode::factory($config)->draw();
    }
}
