<?php
/**
 * FileIndex
 *
 * @package FileIndexingTool
 *
 * @author Tomasz Świenty
 * @version 3.9
 * @copyright Copyright (c) eDokumenty
 */

include_once('../../../vendor/autoload.php');
require_once('ScriptRunner.php');

final class FileIndex {


    private static $fileIndexLog;
    private static $fileIndexStatus;


    /**
     * @param $fileid
     * @param null $host
     * @return bool|int|string
     * @throws Exception
     */
    public static function create($fileid, $host = NULL) {

        if ($host) {
            $_SERVER['HTTP_HOST'] = $host.'.';
        }

        require_once('./classes/Converter/Converter.inc');
        require_once('FileIndexLog.inc');
        require_once('FileIndexStatus.inc');

        self::$fileIndexLog = new FileIndexLog();
        self::$fileIndexLog->write(sprintf('Odpalam FileIndexingTool::FileIndex dla fileid %s', $fileid));

        self::$fileIndexStatus = new FileIndexStatus($fileid);

        $file = new File($fileid);
        if (!$file->URI) {
            self::$fileIndexLog->error(sprintf('Plik o identyfikatorze %s (files.fileid) nie posiada uri', $fileid));
            self::$fileIndexStatus->setStatus('Plik nie posiada uri');

            return '';
        }

        $location = FileLocation::createByURI($file->URI);
        $uri = $location->get($file->URI);
        if (!file_exists($uri)) {
            self::$fileIndexLog->error(sprintf('Brak pliku w lokalizacji %s', $uri));
            self::$fileIndexStatus->setStatus(sprintf('Brak pliku w lokalizacji %s', $uri));

            return '';
        }

        if (!is_readable($uri)) {
            self::$fileIndexLog->error(sprintf('Brak prawa do odczytu pliku w lokalizacji %s', $uri));
            self::$fileIndexStatus->setStatus(sprintf('Brak prawa do odczytu pliku w lokalizacji %s', $uri));

            return '';
        }

        $db = new PgManager(DB_NAME);

        $mtyp = MimeType::get($uri, NULL, $file->type);

        $res = FALSE;
        if ($mtyp == 'text/plain') {
            $res = $db->update('files', array('idxdat' => date('Y-m-d H:i:s'), 'metada' => file_get_contents($uri)), 'fileid = '.$file->fileId);
            $file->addHistory('Indeksowanie zawartości', NULL, 1, 'INDEXED');

            self::$fileIndexStatus->setStatus('Zaindeksowano poprawnie', FALSE);

            $db->commit();
        } else {
            $tmpPath = VarPathService::getTmpPath();
            $previewFile = realpath($tmpPath).'/f'.$file->fileId.'_'.$file->size.'.txt';
            if (file_exists($previewFile)) {
                bs_unlink($previewFile);
            }

            $db->commit();
            try {
                clearstatcache();

                if (strpos($mtyp, 'image') !== 0) {
                    $converter = new Converter($mtyp, 'text/plain');
                    if (get_class($converter->getFilter()) == 'NullFilter') {
                        if (file_exists($previewFile)) {
                            bs_unlink($previewFile);
                        }

                        throw new Exception(sprintf('Brak możliwości konwersji z %s na %s', $mtyp, 'text/plain'));
                    } else {
                        $converter->setOutFile($previewFile);
                        try {
                            $convFile = $converter->convertFromFile($uri);
                            if (!file_exists($previewFile) OR !filesize($previewFile)) {
                                //throw new Exception('Wystąpił nieokreślony błąd podczas indeksowania');
                            }
                        } catch (Exception $e) {
                            //throw new Exception(sprintf('Błąd %s', $e->getMessage()));
                        }
                    }
                }

                clearstatcache();

                if (!file_exists($previewFile) OR !filesize($previewFile)) {
                    if (self::doOCR($uri, $previewFile, $fileid)) {
                        $res = $db->update('files', array('idxdat' => date('Y-m-d H:i:s'), 'metada' => file_get_contents($previewFile)), 'fileid = '.$file->fileId);
                        $file->addHistory('Indeksowanie zawartości', NULL, 1, 'INDEXED');

                        self::$fileIndexStatus->setStatus('Zaindeksowano poprawnie', FALSE);
                        $db->commit();
                    }
                } else {
                    $res = $db->update('files', array('idxdat' => date('Y-m-d H:i:s'), 'metada' => file_get_contents($previewFile)), 'fileid = '.$file->fileId);
                    $file->addHistory('Indeksowanie zawartości', NULL, 1, 'INDEXED');

                    self::$fileIndexStatus->setStatus('Zaindeksowano poprawnie', FALSE);
                    $db->commit();
                }
            } catch (Exception $e) {
                self::$fileIndexLog->error(sprintf('Wystąpił wyjątek podczas indeksowania dla pliku %s: %s', $uri, $e->getMessage()));

                self::$fileIndexStatus->setStatus($e->getMessage());
                $db->commit();
            }
        }

        if (isset($previewFile) AND file_exists($previewFile)) {
            bs_unlink($previewFile);
        }

        return $res;

    }


    /**
     * @param $filePath
     * @param $ocrPath
     * @param $fileid
     * @return bool
     * @throws Exception
     */
    private static function doOCR($filePath, $ocrPath, $fileid) {

        $dir = realpath(VarPathService::getTmpPath()).DIRECTORY_SEPARATOR.''.$fileid.'_ocr_'.time();
        $input = FALSE;

        try {
            if (is_dir($dir)) {
                bs_remove($dir, TRUE);
            }

            if (!bs_mkdir($dir)) {
                throw new Exception(sprintf('Nie można utworzyć katalogu %s', $dir));
            }

            if (preg_match('/pdf$/i', $filePath)) {
                $res = exec('pdfimages -j "'.$filePath.'" "'.$dir.DIRECTORY_SEPARATOR.'img"'. " 2>&1", $arr, $exitCode);
                if ($exitCode) {
                    throw new Exception(__CLASS__.'::'.__LINE__.' -	['.$exitCode.']:	'.implode(' ', $arr).'');
                }

                $filesCount = 0;
                foreach (new DirectoryIterator($dir) as $entry) {
                    if (!$entry->isFile() || (strpos($entry->getFilename(), 'img') !== 0)) continue;
                    $filesCount++;
                }
                if ($filesCount > 3) {
                    $input = $dir.DIRECTORY_SEPARATOR.'image.tif';

                    $res = exec('convert "'.$dir.DIRECTORY_SEPARATOR.'img*.*" "'.$input.'"'. " 2>&1", $arr, $exitCode);
                    if ($exitCode || !file_exists($input)) {
                        throw new Exception(__CLASS__.'::'.__LINE__.' -	['.$exitCode.']:	'.implode(' ', $arr).'');
                    }
                } else {
                    foreach (new DirectoryIterator($dir) as $entry) {
                        if (!$entry->isFile() || (strpos($entry->getFilename(), 'img') !== 0)) continue;
                        $input = $entry->getPathname();
                    }
                }
            }

            if (preg_match('/image\//', MimeType::get($filePath))) {
                $input = $filePath;
            }

            if (!$input) {
                return FALSE;
            }

            $prefix = $dir.DIRECTORY_SEPARATOR.'ocr';
            $res = exec('tesseract "'.$input.'" "'.$prefix.'" -l pol'. " 2>&1", $arr, $exitCode);
            if ($exitCode) {
                throw new Exception(__CLASS__.'::'.__LINE__.' -	['.$exitCode.']:	'.implode(' ', $arr).'');
            }

            if ($input != $filePath) {
                unlink($input);
            }

            rename($prefix.'.txt', $ocrPath);

            return TRUE;
        } catch (Exception $e) {
            throw $e;
        }

    }

}

$args = [];
if (isset($_SERVER['argv'])) {
    $args = $_SERVER['argv'];
    array_shift($args);
}

if (!isset($args[0]) OR (filter_var($args[0], FILTER_VALIDATE_INT, ['options' => ['min_range' => 1]]) === FALSE)) {
    echo sprintf('Błędny parametr %s', json_encode($args));
    exit;
}

$fileid = $args[0];
$host = (isset($args[1]) AND !bs_empty_str($args[1])) ? $args[1] : FALSE;

FileIndex::create($fileid, $host);