<?php

namespace IMATHUZH\Qfq\Core\Form\FormElement;

use IMATHUZH\Qfq\Core\Form\Form;
use IMATHUZH\Qfq\Core\Form\FormElement\AbstractFormElement;
use IMATHUZH\Qfq\Core\Helper\HelperFile;
use IMATHUZH\Qfq\Core\Helper\HelperFormElement;
use IMATHUZH\Qfq\Core\Helper\KeyValueStringParser;
use IMATHUZH\Qfq\Core\Helper\Path;
use IMATHUZH\Qfq\Core\Helper\Support;

class AnnotateFormElement extends AbstractFormElement {
    public array $fabricHtmlAttributes = array();

    /**
     * @param $attributes
     * @param Form|null $form
     * @throws \CodeException
     * @throws \DbException
     * @throws \DownloadException
     * @throws \PhpOffice\PhpSpreadsheet\Exception
     * @throws \PhpOffice\PhpSpreadsheet\Reader\Exception
     * @throws \PhpOffice\PhpSpreadsheet\Writer\Exception
     * @throws \Twig\Error\LoaderError
     * @throws \Twig\Error\RuntimeError
     * @throws \Twig\Error\SyntaxError
     * @throws \UserFormException
     * @throws \UserReportException
     */
    public function __construct($attributes, ?Form $form = null) {
        parent::__construct($attributes, $form);

        if (!isset($this->attributes[FE_ANNOTATE_TYPE])) $this->attributes[FE_ANNOTATE_TYPE] = FE_ANNOTATE_TYPE_GRAPHIC;

        // Prepare HTML attributes for hidden input element
        $this->htmlAttributes[HTML_ATTR_TYPE] = 'hidden';
        $this->htmlAttributes[HTML_ATTR_VALUE] = htmlentities($this->value);
        $this->htmlAttributes[ATTRIBUTE_DATA_REFERENCE] = $this->attributes[FE_DATA_REFERENCE];

        if ($this->attributes[FE_ANNOTATE_TYPE] == FE_ANNOTATE_TYPE_GRAPHIC) {
            $this->prepareAnnotateGraphic();
        } else {
            $this->prepareAnnotateCode();
        }

    }


    /**
     * Prepares the FE to be used or rendered as an image annotation element
     *
     * @return void
     * @throws \CodeException
     * @throws \UserFormException
     */
    private function prepareAnnotateGraphic(): void {
        if (!isset($this->attributes[FE_IMAGE_SOURCE])) {
            throw new \UserFormException("Missing parameter '" . FE_IMAGE_SOURCE . "'", ERROR_IO_READ_FILE);
        }

        clearstatcache();
        if ($this->attributes[FE_IMAGE_SOURCE] != '' && !is_readable($this->attributes[FE_IMAGE_SOURCE])) {
            throw new \UserFormException("Error reading file: " . $this->attributes[FE_IMAGE_SOURCE], ERROR_IO_READ_FILE);
        }

        if (!empty($this->value) && json_decode($this->value) === null) {
            throw new \UserFormException("Fabric data: JSON structure not valid", ERROR_BROKEN_JSON_STRUCTURE);
        }

        // Prepare HTML attributes for Fabric element
        $this->fabricHtmlAttributes[HTML_ATTR_CLASS] = ANNOTATE_GRAPHIC_CSS_CLASS;
        $this->fabricHtmlAttributes["data-background-image"] = $this->fileToSipUrl($this->attributes[FE_IMAGE_SOURCE]);
        $this->fabricHtmlAttributes["data-control-name"] = $this->attributes[FE_HTML_ID];
        $this->fabricHtmlAttributes["data-buttons"] = Path::urlExt('Resources/Public/Json/fabric.buttons.json');
        $this->fabricHtmlAttributes["data-emojis"] = Path::urlExt('Resources/Public/Json/qfq.emoji.json');
        $this->fabricHtmlAttributes["data-fabric-color"] = str_replace("\"", "&quot;", HelperFormElement::penColorToHex($this->attributes));

        if ($this->attributes[FE_MODE] == FE_MODE_READONLY) {
            $this->fabricHtmlAttributes["data-view-only"] = 'true';
        }
    }

    /**
     * Prepares the FE to be used or rendered as a code annotation element
     *
     * @return void
     * @throws \CodeException
     * @throws \UserFormException
     */
    private function prepareAnnotateCode(): void {
        //TODO: implement code annotation if there i s no file, but text, save in a specific column
        if (!isset($this->attributes[FE_TEXT_SOURCE])) {
            throw new \UserFormException("Missing parameter '" . FE_TEXT_SOURCE . "'", ERROR_IO_READ_FILE);
        }

        if (!empty($this->value) && json_decode($this->value) === null) {
            throw new \UserFormException("Annotate data: JSON structure not valid", ERROR_BROKEN_JSON_STRUCTURE);
        }

        Support::setIfNotSet($this->attributes, FE_ANNOTATE_USER_UID);
        Support::setIfNotSet($this->attributes, FE_ANNOTATE_USER_NAME);
        Support::setIfNotSet($this->attributes, FE_ANNOTATE_USER_AVATAR);

        $dataHighlight = HelperFile::getFileTypeHighlight($this->attributes[FE_HIGHLIGHT] ?? '', $this->attributes[FE_TEXT_SOURCE]);

        $jsonDataUid = json_encode(['uid' => $this->attributes[FE_ANNOTATE_USER_UID]
            , 'name' => $this->attributes[FE_ANNOTATE_USER_NAME]
            , 'avatar' => $this->attributes[FE_ANNOTATE_USER_AVATAR]], JSON_UNESCAPED_SLASHES);

        // Prepare HTML attributes for fabric-div
        $this->fabricHtmlAttributes[HTML_ATTR_CLASS] = ANNOTATE_TEXT_CSS_CLASS;
        $this->fabricHtmlAttributes[HTML_ATTR_DATA_FILE] = $this->fileToSipUrl($this->attributes[FE_TEXT_SOURCE]);
        $this->fabricHtmlAttributes['data-target'] = $this->attributes[FE_HTML_ID];
        $this->fabricHtmlAttributes['data-highlight'] = $dataHighlight;
        $this->fabricHtmlAttributes['data-uid'] = str_replace('"', "&quot;", $jsonDataUid);
        if ($this->attributes[FE_MODE] == FE_MODE_READONLY) {
            $this->fabricHtmlAttributes['data-view-only'] = 'true';
        }
    }


    /**
     * @param string $pathFileName
     * @return string SIP encoded URL
     * @throws \CodeException
     * @throws \UserFormException
     */
    private function fileToSipUrl($pathFileName): string {
        $param[DOWNLOAD_MODE] = DOWNLOAD_MODE_FILE;
        $param[SIP_DOWNLOAD_PARAMETER] = base64_encode(TOKEN_FILE . PARAM_TOKEN_DELIMITER . $pathFileName);
        return $this->store->getSipInstance()->queryStringToSip(Path::urlApi(API_DOWNLOAD_PHP) . '?' . KeyValueStringParser::unparse($param, '=', '&'), RETURN_URL);
    }
}