<?php

use idoit\AddOn\RoutingAwareInterface;
use idoit\Component\Helper\ArrayHelper;
use Symfony\Component\Config\FileLocator;
use Symfony\Component\Routing\Loader\PhpFileLoader;

/**
 * i-doit
 *
 * QR-Code module class.
 *
 * @package     i-doit
 * @subpackage  Modules
 * @copyright   synetics GmbH
 * @license     http://www.i-doit.com/license
 */
class isys_module_qrcode extends isys_module implements isys_module_interface, RoutingAwareInterface
{
    /** @var isys_cmdb_dao */
    protected isys_cmdb_dao $dao;

    public function __construct()
    {
        parent::__construct();

        $this->dao = isys_application::instance()->container->get('cmdb_dao');
    }

    /**
     * @param isys_module_request $p_req
     *
     * @return $this
     * @deprecated
     */
    public function init(isys_module_request $p_req)
    {
        return $this;
    }

    /**
     * Method for retrieving the breadcrumb part.
     *
     * @param array $p_gets
     *
     * @return array
     */
    public function breadcrumb_get(&$p_gets)
    {
        return [
            [
                $this->language->get('LC__MODULE__SYSTEM__TREE__PREDEFINED_CONTENT') => [
                    C__GET__MODULE_ID     => C__MODULE__SYSTEM,
                    C__GET__MODULE_SUB_ID => C__MODULE__SYSTEM_SETTINGS,
                    C__GET__SETTINGS_PAGE => 'cmdb-status'
                ]
            ],
            [
                $this->language->get('LC__MODULE__QRCODE') => null
            ]
        ];
    }

    /**
     * Start method.
     */
    public function start()
    {
        if (!isys_auth_system::instance()->has('qr_config')) {
            throw new isys_exception_auth(isys_application::instance()->container->get('language')
                ->get('LC__AUTH__AUTH_EXCEPTION__MISSING_RIGHT_FOR_SYSTEM'));
        }

        // Build the module tree, but only if we are not in the system-module.
        if ($_GET[C__GET__MODULE_ID] != defined_or_default('C__MODULE__SYSTEM')) {
            $redirectUrl = isys_helper_link::create_url([
                C__GET__MODULE_ID     => C__MODULE__SYSTEM,
                C__GET__MODULE_SUB_ID => C__MODULE__QRCODE
            ], true);

            header('Location: ' . $redirectUrl);
            die;
        }

        isys_application::instance()->container->get('template')
            ->assign('content_title', $this->language->get('LC__MODULE__QRCODE'));

        switch ($_GET[C__GET__SETTINGS_PAGE]) {
            default:
                if ($_POST[C__GET__NAVMODE] == C__NAVMODE__SAVE) {
                    try {
                        $l_auth = isys_module_system::getAuth();

                        if (!$l_auth->is_allowed_to(isys_auth::EDIT, 'qr_config/global') && $l_auth->is_allowed_to(isys_auth::EDIT, 'qr_config/objtype')) {
                            throw new isys_exception_auth(isys_application::instance()->container->get('language')
                                ->get('LC__AUTH__AUTH_EXCEPTION__MISSING_RIGHT_FOR_SYSTEM'));
                        }

                        $l_config = [
                            'global'   => [
                                'type'        => $_POST['C__MODULE__QRCODE__GLOBAL_TYPE'] ?: C__QRCODE__TYPE__ACCESS_URL,
                                'link'        => $_POST['C__MODULE__QRCODE__GLOBAL_LINK_TYPE'] ?: C__QRCODE__LINK__PRINT,
                                'description' => $_POST['C__MODULE__QRCODE__CONFIGURATION__GLOBAL_WYSIWYG'] ?: '',
                                'logo'        => $_POST['C__MODULE__QRCODE__LOGO_OBJ__HIDDEN'],
                                'url'         => ($_POST['C__MODULE__QRCODE__GLOBAL_TYPE'] ==
                                C__QRCODE__TYPE__SELFDEFINED ? trim($_POST['C__MODULE__QRCODE__GLOBAL_URL']) : '')
                            ],
                            'obj-type' => []
                        ];

                        if (!empty($l_config['global']['description'])) {
                            $l_config['global']['description'] = $this->purifyDescription($l_config['global']['description']);
                        }

                        foreach ($_POST as $l_key => $l_value) {
                            if (strpos($l_key, 'C__MODULE__QRCODE__WYSIWYG__') === 0) {
                                $l_obj_type = substr($l_key, 28);

                                $l_config['obj-type'][$l_obj_type] = [
                                    'type'        => $_POST['C__MODULE__QRCODE__' . $l_obj_type . '_TYPE'] ?: C__QRCODE__TYPE__ACCESS_URL,
                                    'description' => $_POST['C__MODULE__QRCODE__WYSIWYG__' . $l_obj_type] ?: '',
                                    'url'         => ($_POST['C__MODULE__QRCODE__' . $l_obj_type . '_TYPE'] ==
                                    C__QRCODE__TYPE__SELFDEFINED ? trim($_POST['C__MODULE__QRCODE__' . $l_obj_type . '_URL']) : ''),
                                    'enabled'     => ($_POST['C__MODULE__QRCODE__ENABLE__' . $l_obj_type] == 1)
                                ];

                                if (!empty($l_config['obj-type'][$l_obj_type]['description'])) {
                                    // Necessary action to throw out all tags and attributes, that are not allowed.
                                    $l_config['obj-type'][$l_obj_type]['description'] = $this->purifyDescription($l_config['obj-type'][$l_obj_type]['description']);
                                }
                            }
                        }

                        isys_tenantsettings::set('qrcode.config', $l_config);
                        isys_notify::success(isys_application::instance()->container->get('language')
                            ->get('LC__UNIVERSAL__SUCCESSFULLY_SAVED'));
                    } catch (isys_exception_general $e) {
                        isys_notify::error($e->getMessage(), ['sticky' => true]);
                    }
                }

                $this->process_config();
                break;
        }
    }

    /**
     * @param string $description
     *
     * @return string
     * @throws Exception
     * @see ID-10322
     */
    private function purifyDescription(string $description): string
    {
        $allowedTags = array_unique(ArrayHelper::concat(
            isys_smarty_plugin_f_wysiwyg::get_tags_whitelist(),
            [
                'img',
                'caption',
                'table',
                'thead',
                'th',
                'tbody',
                'tr',
                'td',
                'a',
                's'
            ]
        ));

        $strippedDescription = strip_tags($description, '<' . implode('><', $allowedTags) . '>');

        if (isys_tenantsettings::get('cmdb.registry.sanitize_input_data', 1)) {
            // Necessary action to throw out all tags and attributes, that are not allowed.
            $strippedDescription = isys_application::instance()->container->get('htmlpurifier')->purify($strippedDescription);
        }

        return $strippedDescription;
    }

    /**
     * Method for loading a QR code - That is: it's link, description and logo.
     *
     * @param int $objectId
     *
     * @return array
     * @deprecated Use '\idoit\Module\Qrcode\Component\QrCode->getData()'. This method will be removed in 2025.
     */
    public function load_qr_code($objectId): array
    {
        return (new \idoit\Module\Qrcode\Component\QrCode())->getData((int)$objectId);
    }

    /**
     * Method for processing the QR Code configuration page.
     */
    private function process_config()
    {
        global $index_includes;

        $l_config = isys_tenantsettings::get('qrcode.config');
        $l_auth = isys_module_system::getAuth();

        if (!is_array($l_config)) {
            $l_config = [
                'global'   => [],
                'obj-type' => []
            ];
        }

        $l_navbar = isys_component_template_navbar::getInstance();
        $l_url_description = '';

        if (isys_glob_is_edit_mode()) {
            if ($l_auth->is_allowed_to(isys_auth::EDIT, 'qr_config/global') || $l_auth->is_allowed_to(isys_auth::EDIT, 'qr_config/objtype')) {
                $l_navbar->set_active(true, C__NAVBAR_BUTTON__SAVE);
            }

            $l_navbar->set_active(true, C__NAVBAR_BUTTON__CANCEL);

            $whitelist = filter_defined_constants([
                'C__OBJTYPE__SERVER',
                'C__OBJTYPE__SWITCH',
                'C__OBJTYPE__CLIENT'
            ]);
            // For demonstration purpose we load the first server, switch or client object-ID.
            if (!empty($whitelist)) {
                $l_sql = 'SELECT isys_obj__id FROM isys_obj WHERE isys_obj__isys_obj_type__id IN (' . implode(',', $whitelist) . ') LIMIT 1;';
            } else {
                $l_sql = 'SELECT isys_obj__id FROM isys_obj LIMIT 1;';
            }

            $l_object_id = (int)$this->dao->retrieve($l_sql)
                ->get_row_value('isys_obj__id');

            if (!$l_object_id) {
                $l_object_id = (int)$this->dao->retrieve('SELECT isys_obj__id FROM isys_obj WHERE isys_obj__isys_obj_type__id != ' .
                    $this->dao->convert_sql_id(defined_or_default('C__OBJTYPE__RELATION')) . ' ORDER BY RAND() LIMIT 1;')
                    ->get_row_value('isys_obj__id');
            }

            $l_variables = isys_helper_link::get_url_variables($l_object_id);
        } else {
            if ($l_auth->is_allowed_to(isys_auth::EDIT, 'qr_config/global') || $l_auth->is_allowed_to(isys_auth::EDIT, 'qr_config/objtype')) {
                $l_navbar->set_active(true, C__NAVBAR_BUTTON__EDIT);
            }
        }

        $l_rules = $l_object_types = $l_obj_type_config = [];
        $l_obj_type_data = $this->dao->get_object_type();

        foreach ($l_obj_type_data as $l_object_type) {
            $l_object_types[$l_object_type['isys_obj_type__const']] = $l_object_type['LC_isys_obj_type__title'];

            if (isset($l_config['obj-type'][$l_object_type['isys_obj_type__const']])) {
                $l_obj_type_config[$l_object_type['isys_obj_type__const']] = [
                    'type_selection'   => C__QRCODE__TYPE__ACCESS_URL,
                    'type_selfdefined' => '',
                    'type_accessurl'   => '',
                    'enabled'          => (int)$l_config['obj-type'][$l_object_type['isys_obj_type__const']]['enabled'],
                    'obj_type_name'    => isys_application::instance()->container->get('language')
                        ->get($l_object_type['isys_obj_type__title']),
                    'url'              => 'C__MODULE__QRCODE__' . $l_object_type['isys_obj_type__const'] . '_URL',
                    'description'      => 'C__MODULE__QRCODE__WYSIWYG__' . $l_object_type['isys_obj_type__const']
                ];

                $l_rules['C__MODULE__QRCODE__' . $l_object_type['isys_obj_type__const'] .
                '_URL']['p_strValue'] = $l_config['obj-type'][$l_object_type['isys_obj_type__const']]['url'] ?: '%idoit_host%/?objID=%objid%';
                $l_rules['C__MODULE__QRCODE__WYSIWYG__' .
                $l_object_type['isys_obj_type__const']]['p_strValue'] = $l_config['obj-type'][$l_object_type['isys_obj_type__const']]['description'] ?: '';
                $l_rules['C__MODULE__QRCODE__ENABLE__' .
                $l_object_type['isys_obj_type__const']]['p_strSelectedID'] = (int)$l_config['obj-type'][$l_object_type['isys_obj_type__const']]['enabled'];

                if (($l_config['obj-type'][$l_object_type['isys_obj_type__const']]['type'] ?: C__QRCODE__TYPE__ACCESS_URL) == C__QRCODE__TYPE__ACCESS_URL) {
                    $l_obj_type_config[$l_object_type['isys_obj_type__const']]['type_accessurl'] = ' checked="checked"';
                } else {
                    $l_obj_type_config[$l_object_type['isys_obj_type__const']]['type_selfdefined'] = ' checked="checked"';
                    $l_obj_type_config[$l_object_type['isys_obj_type__const']]['type_selection'] = C__QRCODE__TYPE__SELFDEFINED;
                }
            }
        }

        $l_rules['C__MODULE__QRCODE__OBJ_TYPES'] = [
            'p_arData'          => $l_object_types,
            'p_strClass'        => 'input-small',
            'p_bInfoIconSpacer' => 0,
            'p_bDbFieldNN'      => 1
        ];

        $l_rules['C__MODULE__QRCODE__GLOBAL_URL'] = [
            'p_strValue'        => ($l_config['global']['url'] ?: '%idoit_host%/?objID=%objid%'),
            'p_bInfoIconSpacer' => 0,
            'p_bReadonly'       => !$l_auth->is_allowed_to(isys_auth::EDIT, 'qr_config/global')
        ];

        $l_rules['C__MODULE__QRCODE__CONFIGURATION__GLOBAL_WYSIWYG']['p_strValue'] = $l_config['global']['description'] ?: '';
        $l_rules['C__MODULE__QRCODE__LOGO_OBJ']['p_strSelectedID'] = $l_config['global']['logo'] ?: 0;

        isys_application::instance()->container->get('template')
            ->assign('variable_description', $l_variables)
            ->assign('global_type', $l_config['global']['type'] ?: C__QRCODE__TYPE__ACCESS_URL)
            ->assign('link_type', $l_config['global']['link'] ?: C__QRCODE__LINK__PRINT)
            ->assign('empty_value', isys_tenantsettings::get('gui.empty_value', '-'))
            ->assign('obj_type_config', $l_obj_type_config)
            ->assign('auth_edit_global', $l_auth->is_allowed_to(isys_auth::EDIT, 'qr_config/global'))
            ->assign('auth_edit_objtype', $l_auth->is_allowed_to(isys_auth::EDIT, 'qr_config/objtype'))
            ->assign('auth_delete_objtype', $l_auth->is_allowed_to(isys_auth::DELETE, 'qr_config/objtype'))
            ->assign('smarty_yes_no', get_smarty_arr_YES_NO())
            ->smarty_tom_add_rules('tom.content.bottom.content', $l_rules);

        $index_includes['contentbottomcontent'] = self::getPath() . 'templates/config.tpl';
    }

    /**
     * @return void
     */
    public static function registerRouting(): void
    {
        isys_application::instance()->container->get('routes')
            ->addCollection((new PhpFileLoader(new FileLocator(__DIR__)))->load('config/routes.php'));
    }
}
