<?php

namespace App\Libraries;

use InvalidArgumentException;
use Picqer\Barcode\Types\TypeCode128;
use Throwable;

class Code128Barcode
{
    public function toSvg(string $value): string
    {
        $barcode = $this->barcodeData($value);

        $module = 4;
        $height = 180;
        $quiet = 80;
        $width = ($barcode->getWidth() * $module) + ($quiet * 2);
        $x = $quiet;
        $bars = [];

        foreach ($barcode->getBars() as $bar) {
            $barWidth = $bar->getWidth() * $module;

            if ($bar->isBar() && $barWidth > 0) {
                $bars[] = '<rect x="' . $x . '" y="0" width="' . $barWidth . '" height="' . $height . '" fill="#000"/>';
            }

            $x += $barWidth;
        }

        return '<svg xmlns="http://www.w3.org/2000/svg" width="' . $width . '" height="' . $height . '" viewBox="0 0 ' . $width . ' ' . $height . '" preserveAspectRatio="xMidYMid meet" shape-rendering="crispEdges">'
            . '<rect width="100%" height="100%" fill="#fff"/>'
            . implode('', $bars)
            . '</svg>';
    }

    public function toPng(string $value): string
    {
        $barcode = $this->barcodeData($value);
        $module = 5;
        $height = 220;
        $quiet = 100;
        $width = ($barcode->getWidth() * $module) + ($quiet * 2);

        $image = imagecreatetruecolor($width, $height);
        $white = imagecolorallocate($image, 255, 255, 255);
        $black = imagecolorallocate($image, 0, 0, 0);
        imagefilledrectangle($image, 0, 0, $width, $height, $white);

        $x = $quiet;

        foreach ($barcode->getBars() as $bar) {
            $barWidth = $bar->getWidth() * $module;

            if ($bar->isBar() && $barWidth > 0) {
                imagefilledrectangle($image, $x, 0, $x + $barWidth - 1, $height - 1, $black);
            }

            $x += $barWidth;
        }

        ob_start();
        imagepng($image);
        $png = (string) ob_get_clean();
        imagedestroy($image);

        return $png;
    }

    private function barcodeData(string $value)
    {
        $value = trim($value);

        if ($value === '' || preg_match('/[^\x20-\x7E]/', $value)) {
            throw new InvalidArgumentException('Kode barang tidak dapat dibuat menjadi barcode Code 128.');
        }

        try {
            return (new TypeCode128())->getBarcode($value);
        } catch (Throwable $exception) {
            throw new InvalidArgumentException('Kode barang tidak dapat dibuat menjadi barcode Code 128.', 0, $exception);
        }
    }
}
