<?php

namespace App\Soshot;

use App\DataBase\DataBase;
use App\Utils\ResizeToDemande;
use HeadlessChromium\BrowserFactory;
use HeadlessChromium\Page;
use HeadlessChromium\Exception\BrowserConnectionFailed;
use HeadlessChromium\Exception\OperationTimedOut;
use Noodlehaus\Config;

if (!function_exists('n_print')) {
    function n_print($data, $name = '') {
        print_r($data, 1);
    }
}

class MakeThumb {

    private $queuePath = __DIR__ . '/../../cache/queue/';
    private $thumbPath = __DIR__ . '/../../cache/img/';
    private $fileSocket = __DIR__ . '/../../cache/tmp/chrome-php-socket';
    private $fileList = [];
    private $maxGenPerBatch = 2;
    private $demandes = [];
    private $open = false;
    private $conf;
    private $db;
    private $chromePath = '';

    function __construct() {

        $this->conf = (object)Config::load([__DIR__ . '/../../datas/config.default.json', '?' . __DIR__ . '/../../datas/config.json'])->all();
        $this->maxGenPerBatch = $this->conf->maxGenPerBatch;

        $this->chromePath = $this->conf->chromePath;

        foreach (array_slice(glob($this->queuePath . "*.json"), 0, $this->maxGenPerBatch) as $filename) {
            $this->fileList[] = $filename;
        }

        foreach ($this->fileList as $demande) {
            $this->demandes[] = json_decode(file_get_contents($demande));
        }
        $this->db = new DataBase();
    }

    public function compute() {
        foreach ($this->demandes as $demande) {
            $this->db->setParams($demande);

            // todo verif permit type

            if ($this->testComplete($demande->complete) && $demande->type !== 'pdf') {
                if (ResizeToDemande::makeDemande($demande)) {
                    $this->deleteQueue($demande->hmac);
                    $this->db->addUpdate(1);
                }
            } else {
                $this->makeComplete($demande);
                if ($demande->type !== 'pdf') {
                    if (!ResizeToDemande::makeDemande($demande)) {
                        // todo log
                    }
                }
                $this->deleteQueue($demande->hmac);
                $this->db->addUpdate(1);

                $completeDemande = (object)[
                    'hmac' => $demande->hmac,
                    'url' => $demande->url,
                    'type' => 'complete'
                ];
                $complete = new DataBase($completeDemande);
                $complete->addUpdate(1);
            }
            $this->open = true;

            if ($this->open === true) {
                $this->makeComplete(null, true);
            }
        }
    }

    private function deleteQueue($hmac) {
        if (file_exists($this->queuePath . $hmac . '.json')) {
            unlink($this->queuePath . $hmac . '.json');
        }
    }

    private function testComplete($complete) {
        if (file_exists($complete)) {
            return true;
        }
        return false;
    }

    private function makeComplete($demande, $close = false) {
        if (file_exists($this->fileSocket)) {
            $socket = \file_get_contents($this->fileSocket);
            try {
                $browser = BrowserFactory::connectToBrowser($socket);
            } catch (BrowserConnectionFailed $e) {
                $browser = $this->openBrowser();
            }
        } else {
            $factory = new BrowserFactory($this->chromePath);
            $browser = $factory->createBrowser([
                'userAgent' => 'Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)',
                'keepAlive' => true,
                'headless' => true,
                'windowSize'   => [1920, 1080],
                'customFlags' => [
                    '--disable-dev-shm-usage',
                    '--disable-gpu'
                ],
                'noSandbox' => true,
                //'connectionDelay' => 0.8,            // add 0.8 second of delay between each instruction sent to chrome,
                //'debugLogger'     => 'php://stdout',
            ]);
            \file_put_contents($this->fileSocket, $browser->getSocketUri(), LOCK_EX);
        }

        if ($close === true) {
            $socket = \file_get_contents($this->fileSocket);
            $browser = BrowserFactory::connectToBrowser($socket);
            $browser->close();
            unlink($this->fileSocket);
            return true;
        }

        $dir = $this->thumbPath . substr($demande->hmac, 0, 4) . '/';

        if (!is_dir($dir)) {
            mkdir($dir);
        }

        $page = $browser->createPage();
        $page->navigate($demande->url)->waitForNavigation(Page::DOM_CONTENT_LOADED, 15000);
        sleep(4);

        try {
            $page->screenshot([
                'captureBeyondViewport' => true,
                'clip' => $page->getFullPageClip(),
            ])->saveToFile($demande->complete);

            if ($demande->type === 'pdf' || $this->conf->alwaysMakePdf === true) {
                if ($this->conf->alwaysMakePdf === true) {
                    $pdfFile = str_replace($demande->type, 'pdf', $demande->filePath);
                    $pdfFile = str_replace('png', 'pdf', $pdfFile);
                } else {
                    $pdfFile = $demande->filePath;
                }

                $page->pdf([
                    'printBackground' => true,
                    'displayHeaderFooter' => true,
                    'paperWidth' => 8.268,
                    'paperHeight' => 11.693,
                    'scale' => 1
                ])->saveToFile($pdfFile);

                if ($this->conf->alwaysMakePdf === true) {
                    $this->db->addUpdate(1, 'pdf');
                }
            }
            $this->db->addUpdate(1);
        } catch (OperationTimedOut $e) {
            // todo log
            $socket = \file_get_contents($this->fileSocket);
            $browser = BrowserFactory::connectToBrowser($socket);
            $browser->close();
            unlink($this->fileSocket);
            copy(__DIR__ . '/../../src/images/error_thumb.png', $demande->filePath);
            $this->db->addUpdate(2);
        }
    }

    private function openBrowser() {
        $factory = new BrowserFactory($this->chromePath);

        // Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)
        $browser = $factory->createBrowser([
            'userAgent' => 'Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)',
            'keepAlive' => true,
            'headless' => true,
            'windowSize'   => [1920, 1080],
            'customFlags' => [
                '--disable-dev-shm-usage',
                '--disable-gpu'
            ],
            'noSandbox' => true,
        ]);
        \file_put_contents($this->fileSocket, $browser->getSocketUri(), LOCK_EX);
        return $browser;
    }
}