<?php
namespace Mpdf;

class Mpdf {
    private string $html = '';

    public function __construct(array $config = []) {}

    public function WriteHTML(string $html): void {
        $this->html .= $html;
    }

    public function Output(string $filename = '', string $dest = 'I') {
        $pdf = $this->buildPdf($this->html);
        if ($dest === 'F' || $dest === \Mpdf\Output\Destination::FILE) {
            $dir = dirname($filename);
            if (!is_dir($dir)) @mkdir($dir, 0755, true);
            file_put_contents($filename, $pdf);
            return '';
        }
        if ($dest === 'S' || $dest === \Mpdf\Output\Destination::STRING_RETURN) {
            return $pdf;
        }
        if (!headers_sent()) {
            header('Content-Type: application/pdf');
            if ($filename) header('Content-Disposition: inline; filename="' . basename($filename) . '"');
        }
        echo $pdf;
        return '';
    }

    private function buildPdf(string $html): string {
        $text = html_entity_decode(trim(strip_tags(str_replace(['<br>', '<br/>', '<br />', '</p>', '</h1>', '</h2>', '</h3>', '</tr>'], "\n", $html))), ENT_QUOTES, 'UTF-8');
        $lines = preg_split('/\R+/', $text) ?: [];
        $content = "BT\n/F1 11 Tf\n50 790 Td\n";
        $first = true;
        foreach ($lines as $line) {
            $line = trim(preg_replace('/\s+/', ' ', $line));
            if ($line === '') continue;
            $chunks = str_split($line, 95);
            foreach ($chunks as $chunk) {
                if (!$first) $content .= "0 -15 Td\n";
                $content .= '(' . $this->escapePdf($chunk) . ") Tj\n";
                $first = false;
            }
        }
        $content .= "ET";
        $objects = [];
        $objects[] = "1 0 obj\n<< /Type /Catalog /Pages 2 0 R >>\nendobj\n";
        $objects[] = "2 0 obj\n<< /Type /Pages /Kids [3 0 R] /Count 1 >>\nendobj\n";
        $objects[] = "3 0 obj\n<< /Type /Page /Parent 2 0 R /MediaBox [0 0 595 842] /Resources << /Font << /F1 4 0 R >> >> /Contents 5 0 R >>\nendobj\n";
        $objects[] = "4 0 obj\n<< /Type /Font /Subtype /Type1 /BaseFont /Helvetica >>\nendobj\n";
        $objects[] = "5 0 obj\n<< /Length " . strlen($content) . " >>\nstream\n" . $content . "\nendstream\nendobj\n";
        $pdf = "%PDF-1.4\n";
        $offsets = [0];
        foreach ($objects as $object) {
            $offsets[] = strlen($pdf);
            $pdf .= $object;
        }
        $xref = strlen($pdf);
        $pdf .= "xref\n0 " . (count($objects) + 1) . "\n0000000000 65535 f \n";
        for ($i = 1; $i <= count($objects); $i++) {
            $pdf .= sprintf('%010d 00000 n ', $offsets[$i]) . "\n";
        }
        $pdf .= "trailer\n<< /Size " . (count($objects) + 1) . " /Root 1 0 R >>\nstartxref\n" . $xref . "\n%%EOF";
        return $pdf;
    }

    private function escapePdf(string $text): string {
        $text = iconv('UTF-8', 'Windows-1252//TRANSLIT//IGNORE', $text) ?: $text;
        return str_replace(['\\', '(', ')'], ['\\\\', '\\(', '\\)'], $text);
    }
}
