<?php

namespace Admidio\UI\Presenter;

use Admidio\Infrastructure\Exception;
use Admidio\Infrastructure\Utils\SecurityUtils;
use Admidio\Roles\Entity\Role;
use Admidio\Roles\ValueObject\RoleDependency;
use Admidio\Roles\Service\RolesService;
use Admidio\UI\Component\DataTables;
use Admidio\Changelog\Service\ChangelogService;

/**
 * @brief Class with methods to display the module pages and helpful functions.
 *
 * This class adds some functions that are used in the groups and roles module to keep the
 * code easy to read and short
 *
 * **Code example**
 * ```
 * // generate HTML output with available registrations
 * $page = new ModuleGroupsRoles('admidio-groups-roles', $headline);
 * $page->createRegistrationList();
 * $page->show();
 * ```
 * @copyright The Admidio Team
 * @see https://www.admidio.org/
 * @license https://www.gnu.org/licenses/gpl-2.0.html GNU General Public License v2.0 only
 */
class GroupsRolesPresenter extends PagePresenter
{
    /**
     * @var int Type of the role e.g. ROLE_TYPE_INACTIVE, ROLE_TYPE_ACTIVE, ROLE_TYPE_EVENT_PARTICIPATION
     */
    public const ROLE_TYPE_INACTIVE = 0;
    public const ROLE_TYPE_ACTIVE = 1;
    public const ROLE_TYPE_EVENT_PARTICIPATION = 2;

    /**
     * Show all roles of the organization in card view. The roles must be read before with the method readData.
     * The cards will show various functions like activate, deactivate, vcard export, edit or delete. Also, the
     * role information e.g. description, start and end date, number of active and former members. A button with
     * the link to the default list will be shown.
     * @param string $categoryUUID UUID of the category for which the roles should be shown.
     * @param int $roleType The type of roles that should be shown within this page.
     *                         0 - inactive roles
     *                         1 - active roles
     *                         2 - event participation roles
     * @throws \Smarty\Exception|Exception
     * @throws Exception
     */
    public function createCards(string $categoryUUID, int $roleType): void
    {
        global $gSettingsManager, $gCurrentUser, $gCurrentSession, $gL10n, $gDb;

        if (!$gCurrentUser->isAdministratorRoles()) {
            throw new Exception('SYS_NO_RIGHTS');
        }

        $this->createSharedHeader($categoryUUID, $roleType);
        $rolesService = new RolesService($gDb);
        $data = $rolesService->findAll($roleType, $categoryUUID);

        $categoryUUID = '';
        $categoryName = '';
        $templateDataCategory = array();
        $templateDataRoles = array();

        foreach ($data as $row) {
            $role = new Role($gDb);
            $role->setArray($row);

            if ($categoryUUID !== $row['cat_uuid']) {
                if ($categoryUUID !== '') {
                    $templateDataCategory[] = array(
                        'uuid' => $categoryUUID,
                        'name' => $categoryName,
                        'entries' => $templateDataRoles
                    );
                }
                $categoryUUID = $row['cat_uuid'];
                $categoryName = $role->getValue('cat_name');
                $templateDataRoles = array();
            }

            $templateRow = array();
            $templateRow['category'] = $role->getValue('cat_name');
            $templateRow['id'] = 'role_' . $role->getValue('rol_uuid');
            $templateRow['title'] = $role->getValue('rol_name');

            // send mail to all role members
            if ($gCurrentUser->hasRightSendMailToRole($row['rol_id']) && $gSettingsManager->getInt('mail_module_enabled') > 0) {
                $templateRow['actions'][] = array(
                    'url' => SecurityUtils::encodeUrl(ADMIDIO_URL . FOLDER_MODULES . '/messages/messages_write.php', array('role_uuid' => $row['rol_uuid'])),
                    'icon' => 'bi bi-envelope',
                    'tooltip' => $gL10n->get('SYS_EMAIL_TO_MEMBERS')
                );
            }

            // link to assign or remove members if you are allowed to do it
            if ($role->allowedToAssignMembers($gCurrentUser)) {
                $templateRow['actions'][] = array(
                    'url' => SecurityUtils::encodeUrl(ADMIDIO_URL . FOLDER_MODULES . '/groups-roles/members_assignment.php', array('role_uuid' => $row['rol_uuid'])),
                    'icon' => 'bi bi-person-plus',
                    'tooltip' => $gL10n->get('SYS_ASSIGN_MEMBERS')
                );
            }

            if ($gCurrentUser->isAdministratorRoles()) {
                // set a role active or inactive
                if ($roleType === GroupsRolesPresenter::ROLE_TYPE_INACTIVE && !$role->getValue('rol_administrator')) {
                    $templateRow['actions'][] = array(
                        'dataHref' => 'callUrlHideElement(\'role_' . $row['rol_uuid'] . '\', \'' . SecurityUtils::encodeUrl(ADMIDIO_URL . FOLDER_MODULES . '/groups-roles/groups_roles.php', array('mode' => 'activate', 'role_uuid' => $row['rol_uuid'])) . '\', \'' . $gCurrentSession->getCsrfToken() . '\')',
                        'dataMessage' => $gL10n->get('SYS_ACTIVATE_ROLE_DESC', array($row['rol_name'])),
                        'icon' => 'bi bi-eye',
                        'tooltip' => $gL10n->get('SYS_ACTIVATE_ROLE')
                    );
                } elseif ($roleType === GroupsRolesPresenter::ROLE_TYPE_ACTIVE && !$role->getValue('rol_administrator')) {
                    $templateRow['actions'][] = array(
                        'dataHref' => 'callUrlHideElement(\'role_' . $row['rol_uuid'] . '\', \'' . SecurityUtils::encodeUrl(ADMIDIO_URL . FOLDER_MODULES . '/groups-roles/groups_roles.php', array('mode' => 'deactivate', 'role_uuid' => $row['rol_uuid'])) . '\', \'' . $gCurrentSession->getCsrfToken() . '\')',
                        'dataMessage' => $gL10n->get('SYS_DEACTIVATE_ROLE_DESC', array($row['rol_name'])),
                        'icon' => 'bi bi-eye-slash',
                        'tooltip' => $gL10n->get('SYS_DEACTIVATE_ROLE')
                    );
                }

                // edit roles of you are allowed to assign roles
                $templateRow['actions'][] = array(
                    'url' => SecurityUtils::encodeUrl(ADMIDIO_URL . FOLDER_MODULES . '/groups-roles/groups_roles.php', array('mode' => 'edit', 'role_uuid' => $row['rol_uuid'])),
                    'icon' => 'bi bi-pencil-square',
                    'tooltip' => $gL10n->get('SYS_EDIT_ROLE')
                );
                if (!$role->getValue('rol_administrator')) {
                    $templateRow['actions'][] = array(
                        'dataHref' => 'callUrlHideElement(\'role_' . $row['rol_uuid'] . '\', \'' . SecurityUtils::encodeUrl(ADMIDIO_URL . FOLDER_MODULES . '/groups-roles/groups_roles.php', array('mode' => 'delete', 'role_uuid' => $row['rol_uuid'])) . '\', \'' . $gCurrentSession->getCsrfToken() . '\')',
                        'dataMessage' => $gL10n->get('SYS_WANT_DELETE_ENTRY', array($row['rol_name'])),
                        'icon' => 'bi bi-trash',
                        'tooltip' => $gL10n->get('SYS_DELETE_ROLE')
                    );
                }
            }

            if (!empty($role->getValue('rol_description'))) {
                $roleDescription = strip_tags($role->getValue('rol_description'));

                if (strlen($roleDescription) > 200) {
                    // Read the first 200 chars of a text, then search for the last space and cut the text there. After that, add a "more" link
                    $textPrev = substr($roleDescription, 0, 200);
                    $maxPosPrev = strrpos($textPrev, ' ');
                    $roleDescription = substr($textPrev, 0, $maxPosPrev) .
                        ' <span class="collapse" id="viewdetails-' . $row['rol_uuid'] . '">' . substr($roleDescription, $maxPosPrev) . '.
                                </span> <a class="admidio-icon-link" data-bs-toggle="collapse" data-bs-target="#viewdetails-' . $row['rol_uuid'] . '">»</a>';
                }

                $templateRow['information'][] = $roleDescription;
            }

            // Block with information about events and meeting-point
            if (!empty($role->getValue('rol_start_date')) || $role->getValue('rol_weekday') > 0
                || !empty($role->getValue('rol_start_time')) || !empty($role->getValue('rol_location'))) {
                $html = '<h6>' . $gL10n->get('SYS_APPOINTMENTS') . ' / ' . $gL10n->get('SYS_MEETINGS') . '</h6>';
                if ($role->getValue('rol_start_date') !== '') {
                    $html .= '<span class="d-block">' . $gL10n->get('SYS_DATE_FROM_TO', array($role->getValue('rol_start_date', $gSettingsManager->getString('system_date')), $role->getValue('rol_end_date', $gSettingsManager->getString('system_date')))) . '</span>';
                }

                if ($role->getValue('rol_weekday') > 0 || !empty($role->getValue('rol_start_time'))) {
                    if ($role->getValue('rol_weekday') > 0) {
                        $html .= RolesService::getWeekdays($role->getValue('rol_weekday')) . ' ';
                    }
                    if (!empty($role->getValue('rol_start_time'))) {
                        $html .= $gL10n->get('SYS_FROM_TO', array($role->getValue('rol_start_time', $gSettingsManager->getString('system_time')), $role->getValue('rol_end_time', $gSettingsManager->getString('system_time'))));
                    }
                    $html = '<span class="d-block">' . $html . '</span>';
                }

                // Meeting point
                if (!empty($role->getValue('rol_location'))) {
                    $html .= '<span class="d-block">' . $gL10n->get('SYS_MEETING_POINT') . ' ' . $role->getValue('rol_location') . '</span>';
                }
                $templateRow['information'][] = $html;
            }

            // show member fee
            if (!empty($role->getValue('rol_cost')) || $role->getValue('rol_cost_period') > 0) {
                $html = '';

                // Member fee
                if (!empty($role->getValue('rol_cost'))) {
                    $html .= (float)$role->getValue('rol_cost') . ' ' . $gSettingsManager->getString('system_currency');
                }

                // Contributory period
                if (!empty($role->getValue('rol_cost_period')) && $role->getValue('rol_cost_period') != 0) {
                    $html .= ' - ' . Role::getCostPeriods($role->getValue('rol_cost_period'));
                }

                $templateRow['information'][] = '<h6>' . $gL10n->get('SYS_CONTRIBUTION') . '</h6><span class="d-block">' . $html . '</span></li>';
            }

            // show count of members and leaders of this role
            $html = '';

            if ($role->getValue('rol_max_members') > 0) {
                $html .= '<span class="d-block">' . $gL10n->get('SYS_MAX_PARTICIPANTS_OF_ROLE', array((int)$row['num_members'], (int)$role->getValue('rol_max_members'))) . '</span>';
            } else {
                $html .= '<span class="d-block">' . $row['num_members'] . ' ' . $gL10n->get('SYS_PARTICIPANTS') . '</span>';
            }

            if ($row['num_leader'] > 0) {
                $html .= '<span class="d-block">' . $row['num_leader'] . ' ' . $gL10n->get('SYS_LEADERS') . '</span>';
            }

            if ($gCurrentUser->hasRightViewFormerRolesMembers($row['rol_id']) && $roleType === $this::ROLE_TYPE_ACTIVE && $row['num_former'] > 0) {
                // show former members
                if ($row['num_former'] == 1) {
                    $textFormerMembers = $gL10n->get('SYS_FORMER');
                } else {
                    $textFormerMembers = $gL10n->get('SYS_FORMER_PL');
                }

                $html .= '<span class="d-block">' . $row['num_former'] . ' ' . $textFormerMembers . '</span>';
            }

            $templateRow['information'][] = $html;

            $templateRow['buttons'][] = array(
                'url' => SecurityUtils::encodeUrl(ADMIDIO_URL . FOLDER_MODULES . '/groups-roles/lists_show.php', array('role_list' => $row['rol_uuid'])),
                'name' => $gL10n->get('SYS_SHOW_MEMBER_LIST')
            );

            $templateDataRoles[] = $templateRow;
        }
        $templateDataCategory[] = array(
            'uuid' => $categoryUUID,
            'name' => $categoryName,
            'entries' => $templateDataRoles
        );
        $this->smarty->assign('cards', $templateDataCategory);
        $this->smarty->assign('l10n', $gL10n);
        $this->pageContent .= $this->smarty->fetch('modules/groups-roles.cards.tpl');
    }

    /**
     * Create the data for the edit form of a role.
     * @param string $roleUUID UUID of the role that should be edited.
     * @throws Exception
     */
    public function createEditForm(string $roleUUID = ''): void
    {
        global $gCurrentOrgId, $gCurrentUser, $gCurrentSession, $gDb, $gL10n, $gSettingsManager;

        // Initialize local parameters
        $eventRole = false;

        // create role object
        $role = new Role($gDb);

        if ($roleUUID !== '') {
            $role->readDataByUuid($roleUUID);
            if (!$role->isVisible()) {
                throw new Exception('SYS_NO_RIGHTS');
            }

            $eventRole = $role->getValue('cat_name_intern') === 'EVENTS';

            // administrator role could only be created or edited by administrators
            if ($role->getValue('rol_administrator') == 1 && !$gCurrentUser->isAdministrator()) {
                throw new Exception('SYS_NO_RIGHTS');
            }
        }

        // get all dependent roles of this role
        $childRoles = RoleDependency::getChildRoles($gDb, $role->getValue('rol_id'));

        $this->addJavascript('
            checkMaxMemberCount();
            $("#rol_assign_roles").change(function() {
                markRoleRight("rol_assign_roles", "rol_all_lists_view", true);
            });
            $("#rol_all_lists_view").change(function() {
                markRoleRight("rol_all_lists_view", "rol_assign_roles", false);
            });
            $("#rol_max_members").change(function() {
                checkMaxMemberCount();
            });',
            true
        );

        $this->addJavascript('
            /**
             * show/hide role dependencies if max count members will be changed
             */
            function checkMaxMemberCount() {
                // If a maximum number of members has been specified, no role dependencies may exist
                if ($("#rol_max_members").val() > 0) {
                    $("#gb_dependencies").hide();

                    // All dependent roles are marked and set to independent
                    $("#dependent_roles").val("");
                } else {
                    $("#gb_dependencies").show();
                }
            }

            /**
             * Set dependent role right if another role right changed
             * @param {string} srcRight  ID of the right that triggers the event
             * @param {string} destRight ID of the right that is to be adapted
             * @param {bool}   checked   true destRight is set to checked
             *                           false destRight is set to unchecked
             */
            function markRoleRight(srcRight, destRight, checked) {
                if (document.getElementById(srcRight).checked && checked) {
                    document.getElementById(destRight).checked = true;
                }
                if (!document.getElementById(srcRight).checked && !checked) {
                    document.getElementById(destRight).checked = false;
                }
            }
        ');

        ChangelogService::displayHistoryButton($this, 'roles', 'roles', !empty($getAnnroleUUIDUuid), array('uuid' => $roleUUID));

        $form = new FormPresenter(
            'adm_roles_edit_form',
            'modules/groups-roles.edit.tpl',
            SecurityUtils::encodeUrl(ADMIDIO_URL . FOLDER_MODULES . '/groups-roles/groups_roles.php', array('role_uuid' => $roleUUID, 'mode' => 'save')),
            $this
        );

        if ($role->getValue('rol_administrator') === 1 || $eventRole) {
            $fieldProperty = FormPresenter::FIELD_READONLY;
        } else {
            $fieldProperty = FormPresenter::FIELD_REQUIRED;
        }
        $form->addInput(
            'rol_name',
            $gL10n->get('SYS_NAME'),
            $role->getValue('rol_name'),
            array('maxLength' => 100, 'property' => $fieldProperty)
        );
        $form->addMultilineTextInput(
            'rol_description',
            $gL10n->get('SYS_DESCRIPTION'),
            $role->getValue('rol_description'),
            3,
            array('property' => ($eventRole ? FormPresenter::FIELD_READONLY : FormPresenter::FIELD_DEFAULT), 'maxLength' => 4000)
        );
        $form->addSelectBoxForCategories(
            'rol_cat_id',
            $gL10n->get('SYS_CATEGORY'),
            $gDb,
            ($eventRole ? 'ROL_EVENT' : 'ROL'),
            FormPresenter::SELECT_BOX_MODUS_EDIT,
            array('property' => ($eventRole ? FormPresenter::FIELD_READONLY : FormPresenter::FIELD_REQUIRED), 'defaultValue' => $role->getValue('cat_uuid'))
        );
        if ($gSettingsManager->getInt('mail_module_enabled') > 0) {
            $selectBoxEntries = array(0 => $gL10n->get('SYS_NOBODY'), 1 => $gL10n->get('SYS_ROLE_MEMBERS'), 2 => $gL10n->get('ORG_REGISTERED_USERS'), 3 => $gL10n->get('SYS_ALSO_VISITORS'));
            $form->addSelectBox(
                'rol_mail_this_role',
                $gL10n->get('SYS_SEND_MAILS'),
                $selectBoxEntries,
                array(
                    'defaultValue' => $role->getValue('rol_mail_this_role'),
                    'showContextDependentFirstEntry' => false,
                    'helpTextId' => $gL10n->get('SYS_RIGHT_MAIL_THIS_ROLE_DESC', array('SYS_RIGHT_MAIL_TO_ALL'))
                )
            );
        }
        $selectBoxEntries = array(0 => $gL10n->get('SYS_NOBODY'), 3 => $gL10n->get('SYS_LEADERS'), 1 => $gL10n->get('SYS_ROLE_MEMBERS'), 2 => $gL10n->get('ORG_REGISTERED_USERS'));
        $form->addSelectBox(
            'rol_view_memberships',
            $gL10n->get('SYS_VIEW_ROLE_MEMBERSHIPS'),
            $selectBoxEntries,
            array(
                'defaultValue' => $role->getValue('rol_view_memberships'),
                'showContextDependentFirstEntry' => false,
                'helpTextId' => $gL10n->get('SYS_VIEW_ROLE_MEMBERSHIPS_DESC', array('SYS_RIGHT_ALL_LISTS_VIEW'))
            )
        );
        $form->addSelectBox(
            'rol_view_members_profiles',
            $gL10n->get('SYS_VIEW_PROFILES_OF_ROLE_MEMBERS'),
            $selectBoxEntries,
            array(
                'defaultValue' => $role->getValue('rol_view_members_profiles'),
                'showContextDependentFirstEntry' => false,
                'helpTextId' => $gL10n->get('SYS_VIEW_PROFILES_OF_ROLE_MEMBERS_DESC', array('SYS_RIGHT_ALL_LISTS_VIEW'))
            )
        );
        $selectBoxEntries = array(0 => $gL10n->get('SYS_NO_ADDITIONAL_RIGHTS'), 1 => $gL10n->get('SYS_ASSIGN_MEMBERS'), 2 => $gL10n->get('SYS_EDIT_MEMBERS'), 3 => $gL10n->get('SYS_ASSIGN_EDIT_MEMBERS'));
        $form->addSelectBox(
            'rol_leader_rights',
            $gL10n->get('SYS_LEADER'),
            $selectBoxEntries,
            array(
                'defaultValue' => $role->getValue('rol_leader_rights'),
                'showContextDependentFirstEntry' => false,
                'helpTextId' => 'SYS_LEADER_RIGHTS_DESC'
            )
        );

        $selectBoxEntries = array(0 => $gL10n->get('SYS_SYSTEM_DEFAULT_LIST'));
        // Prepare SQL statement for all list configurations to be displayed
        $sql = 'SELECT lst_id, lst_name
          FROM ' . TBL_LISTS . '
         WHERE lst_org_id = ? -- $gCurrentOrgId
           AND lst_global = true
           AND lst_name IS NOT NULL
      ORDER BY lst_global, lst_name';
        $pdoStatement = $gDb->queryPrepared($sql, array($gCurrentOrgId));

        while ($row = $pdoStatement->fetch()) {
            $selectBoxEntries[$row['lst_id']] = $row['lst_name'];
        }
        $form->addSelectBox(
            'rol_lst_id',
            $gL10n->get('SYS_DEFAULT_LIST'),
            $selectBoxEntries,
            array('defaultValue' => (int)$role->getValue('rol_lst_id'), 'showContextDependentFirstEntry' => false, 'helpTextId' => 'SYS_DEFAULT_LIST_DESC')
        );

        if (!$eventRole) {
            $form->addCheckbox(
                'rol_default_registration',
                $gL10n->get('SYS_DEFAULT_ASSIGNMENT_REGISTRATION'),
                (bool)$role->getValue('rol_default_registration'),
                array('helpTextId' => 'SYS_DEFAULT_ASSIGNMENT_REGISTRATION_DESC')
            );
            $form->addInput(
                'rol_max_members',
                $gL10n->get('SYS_MAX_PARTICIPANTS') . '<br />(' . $gL10n->get('SYS_NO_LEADER') . ')',
                (int)$role->getValue('rol_max_members'),
                array('type' => 'number', 'minNumber' => 0, 'maxNumber' => 99999, 'step' => 1)
            );
            $form->addInput(
                'rol_cost',
                $gL10n->get('SYS_CONTRIBUTION') . ' ' . $gSettingsManager->getString('system_currency'),
                (string)$role->getValue('rol_cost'),
                array('type' => 'number', 'minNumber' => 0, 'maxNumber' => 99999, 'step' => '0.01')
            );
            $form->addSelectBox(
                'rol_cost_period',
                $gL10n->get('SYS_CONTRIBUTION_PERIOD'),
                Role::getCostPeriods(),
                array('defaultValue' => $role->getValue('rol_cost_period'), 'class' => 'form-control-small')
            );
        }

        $roleName = $gL10n->get('SYS_NEW_ROLE');

        // event roles should not set rights, events meetings and dependencies
        if (!$eventRole) {
            $form->addCheckbox(
                'rol_assign_roles',
                $gL10n->get('SYS_RIGHT_ASSIGN_ROLES'),
                (bool)$role->getValue('rol_assign_roles'),
                array('helpTextId' => 'SYS_RIGHT_ASSIGN_ROLES_DESC', 'icon' => 'bi-people-fill')
            );
            $form->addCheckbox(
                'rol_all_lists_view',
                $gL10n->get('SYS_RIGHT_ALL_LISTS_VIEW'),
                (bool)$role->getValue('rol_all_lists_view'),
                array('icon' => 'bi-list-task')
            );
            $form->addCheckbox(
                'rol_approve_users',
                $gL10n->get('SYS_RIGHT_APPROVE_USERS'),
                (bool)$role->getValue('rol_approve_users'),
                array('icon' => 'bi-card-checklist')
            );
            if ($gSettingsManager->getInt('mail_module_enabled') > 0) {
                $form->addCheckbox(
                    'rol_mail_to_all',
                    $gL10n->get('SYS_RIGHT_MAIL_TO_ALL'),
                    (bool)$role->getValue('rol_mail_to_all'),
                    array('icon' => 'bi-envelope-fill')
                );
            }
            $form->addCheckbox(
                'rol_edit_user',
                $gL10n->get('SYS_RIGHT_EDIT_USER'),
                (bool)$role->getValue('rol_edit_user'),
                array('helpTextId' => 'SYS_RIGHT_EDIT_USER_DESC', 'icon' => 'bi-person-fill-gear')
            );
            $form->addCheckbox(
                'rol_profile',
                $gL10n->get('SYS_RIGHT_PROFILE'),
                (bool)$role->getValue('rol_profile'),
                array('icon' => 'bi-person-fill')
            );
            if ($gSettingsManager->getInt('announcements_module_enabled') > 0) {
                $form->addCheckbox(
                    'rol_announcements',
                    $gL10n->get('SYS_RIGHT_ANNOUNCEMENTS'),
                    (bool)$role->getValue('rol_announcements'),
                    array('helpTextId' => 'SYS_ROLES_MODULE_ADMINISTRATORS_DESC', 'icon' => 'bi-newspaper')
                );
            }
            if ($gSettingsManager->getInt('events_module_enabled') > 0) {
                $form->addCheckbox(
                    'rol_events',
                    $gL10n->get('SYS_RIGHT_DATES'),
                    (bool)$role->getValue('rol_events'),
                    array('helpTextId' => 'SYS_ROLES_MODULE_ADMINISTRATORS_DESC', 'icon' => 'bi-calendar-week-fill')
                );
            }
            if ($gSettingsManager->getInt('photo_module_enabled') > 0) {
                $form->addCheckbox(
                    'rol_photo',
                    $gL10n->get('SYS_RIGHT_PHOTOS'),
                    (bool)$role->getValue('rol_photo'),
                    array('icon' => 'bi-image-fill')
                );
            }
            if ($gSettingsManager->getInt('documents_files_module_enabled') > 0) {
                $form->addCheckbox(
                    'rol_documents_files',
                    $gL10n->get('SYS_RIGHT_DOCUMENTS_FILES'),
                    (bool)$role->getValue('rol_documents_files'),
                    array('helpTextId' => 'SYS_RIGHT_DOCUMENTS_FILES_DESC', 'icon' => 'bi-file-earmark-arrow-down-fill')
                );
            }
            if ($gSettingsManager->get('inventory_module_enabled') > 0) {
                $form->addCheckbox(
                    'rol_inventory_admin',
                    $gL10n->get('SYS_RIGHT_INVENTORY'),
                    (bool)$role->getValue('rol_inventory_admin'),
                    array('helpTextId' => 'SYS_RIGHT_INVENTORY_DESC', 'icon' => 'bi-box-seam-fill')
                );
            }
            if ($gSettingsManager->getInt('forum_module_enabled') > 0) {
                $form->addCheckbox(
                    'rol_forum_admin',
                    $gL10n->get('SYS_RIGHT_FORUM'),
                    (bool)$role->getValue('rol_forum_admin'),
                    array('helpTextId' => 'SYS_RIGHT_FORUM_DESC', 'icon' => 'bi-chat-dots-fill')
                );
            }
            if ($gSettingsManager->getInt('weblinks_module_enabled') > 0) {
                $form->addCheckbox(
                    'rol_weblinks',
                    $gL10n->get('SYS_RIGHT_WEBLINKS'),
                    (bool)$role->getValue('rol_weblinks'),
                    array('helpTextId' => 'SYS_ROLES_MODULE_ADMINISTRATORS_DESC', 'icon' => 'bi-link-45deg')
                );
            }
            $form->addInput('rol_start_date', $gL10n->get('SYS_VALID_FROM'), $role->getValue('rol_start_date'), array('type' => 'date'));
            $form->addInput('rol_end_date', $gL10n->get('SYS_VALID_TO'), $role->getValue('rol_end_date'), array('type' => 'date'));
            $form->addInput('rol_start_time', $gL10n->get('SYS_TIME_FROM'), $role->getValue('rol_start_time'), array('type' => 'time'));
            $form->addInput('rol_end_time', $gL10n->get('SYS_TIME_TO'), $role->getValue('rol_end_time'), array('type' => 'time'));
            $form->addSelectBox('rol_weekday', $gL10n->get('SYS_WEEKDAY'), RolesService::getWeekdays(), array('defaultValue' => $role->getValue('rol_weekday'), 'class' => 'form-control-small'));
            $form->addInput('rol_location', $gL10n->get('SYS_MEETING_POINT'), $role->getValue('rol_location'), array('maxLength' => 100));

            if ($role->getValue('rol_name') !== '') {
                $roleName = $gL10n->get('SYS_ROLE') . ' <strong>' . $role->getValue('rol_name') . '</strong>';
            }

            //  list all roles that the user is allowed to see
            $sqlData['query'] = 'SELECT rol_id, rol_name, cat_name
                           FROM ' . TBL_ROLES . '
                     INNER JOIN ' . TBL_CATEGORIES . '
                             ON cat_id = rol_cat_id
                          WHERE rol_valid   = true
                            AND cat_name_intern <> \'EVENTS\'
                            AND (  cat_org_id  = ? -- $gCurrentOrgId
                                OR cat_org_id IS NULL )
                       ORDER BY cat_sequence, rol_name';
            $sqlData['params'] = array($gCurrentOrgId);

            $form->addSelectBoxFromSql(
                'dependent_roles',
                $gL10n->get('SYS_DEPENDENT'),
                $gDb,
                $sqlData,
                array('defaultValue' => $childRoles, 'multiselect' => true)
            );
        }

        $form->addSubmitButton('adm_button_save', $gL10n->get('SYS_SAVE'), array('icon' => 'bi-check-lg'));

        $this->assignSmartyVariable('eventRole', $eventRole);
        $this->assignSmartyVariable('roleName', $roleName);
        $this->assignSmartyVariable('userCreatedName', $role->getNameOfCreatingUser());
        $this->assignSmartyVariable('userCreatedTimestamp', $role->getValue('rol_timestamp_create'));
        $this->assignSmartyVariable('lastUserEditedName', $role->getNameOfLastEditingUser());
        $this->assignSmartyVariable('lastUserEditedTimestamp', $role->getValue('rol_timestamp_change'));
        $form->addToHtmlPage();
        $gCurrentSession->addFormObject($form);
    }

    /**
     * Show all roles of the organization in card view. The roles must be read before with the method readData.
     * The cards will show various functions like activate, deactivate, vcard export, edit or delete. Also, the
     * role information e.g. description, start and end date, number of active and former members. A button with
     * the link to the default list will be shown.
     * @param string $categoryUUID UUID of the category for which the roles should be shown.
     * @param string $roleType The type of roles that should be shown within this page.
     *                         0 - inactive roles
     *                         1 - active roles
     *                         2 - event participation roles
     * @throws \Smarty\Exception|Exception
     * @throws Exception
     */
    public function createPermissionsList(string $categoryUUID, string $roleType): void
    {
        global $gSettingsManager, $gL10n, $gDb, $gCurrentSession, $gCurrentUser;

        if (!$gCurrentUser->isAdministratorRoles()) {
            throw new Exception('SYS_NO_RIGHTS');
        }

        $templateData = array();
        $this->createSharedHeader($categoryUUID, $roleType, 'permissions');

        $rolesService = new RolesService($gDb);
        $data = $rolesService->findAll($roleType, $categoryUUID);

        foreach ($data as $row) {
            $role = new Role($gDb);
            $role->setArray($row);

            $templateRow = array();
            $templateRow['category'] = $role->getValue('cat_name');
            $templateRow['categoryOrder'] = $role->getValue('cat_sequence');
            $templateRow['role'] = $role->getValue('rol_name');
            $templateRow['roleUUID'] = $role->getValue('rol_uuid');
            $templateRow['roleUrl'] = SecurityUtils::encodeUrl(ADMIDIO_URL . FOLDER_MODULES . '/groups-roles/groups_roles.php', array('mode' => 'edit', 'role_uuid' => $row['rol_uuid']));
            $templateRow['roleRights'] = array();
            if ($role->getValue('rol_assign_roles') == 1) {
                $templateRow['roleRights'][] = array('icon' => 'bi bi-people-fill', 'title' => $gL10n->get('SYS_RIGHT_ASSIGN_ROLES'));
            }
            if ($role->getValue('rol_all_lists_view') == 1) {
                $templateRow['roleRights'][] = array('icon' => 'bi bi-list-task', 'title' => $gL10n->get('SYS_RIGHT_ALL_LISTS_VIEW'));
            }
            if ($role->getValue('rol_approve_users') == 1) {
                $templateRow['roleRights'][] = array('icon' => 'bi bi-card-checklist', 'title' => $gL10n->get('SYS_RIGHT_APPROVE_USERS'));
            }
            if ($role->getValue('rol_mail_to_all') == 1) {
                $templateRow['roleRights'][] = array('icon' => 'bi bi-envelope-fill', 'title' => $gL10n->get('SYS_RIGHT_MAIL_TO_ALL'));
            }
            if ($role->getValue('rol_edit_user') == 1) {
                $templateRow['roleRights'][] = array('icon' => 'bi bi-person-fill-gear', 'title' => $gL10n->get('SYS_RIGHT_EDIT_USER'));
            }
            if ($role->getValue('rol_profile') == 1) {
                $templateRow['roleRights'][] = array('icon' => 'bi bi-person-fill', 'title' => $gL10n->get('SYS_RIGHT_PROFILE'));
            }
            if ($role->getValue('rol_announcements') == 1 && $gSettingsManager->getInt('announcements_module_enabled') > 0) {
                $templateRow['roleRights'][] = array('icon' => 'bi bi-newspaper', 'title' => $gL10n->get('SYS_RIGHT_ANNOUNCEMENTS'));
            }
            if ($role->getValue('rol_events') == 1 && $gSettingsManager->getInt('events_module_enabled') > 0) {
                $templateRow['roleRights'][] = array('icon' => 'bi bi-calendar-week-fill', 'title' => $gL10n->get('SYS_RIGHT_DATES'));
            }
            if ($role->getValue('rol_photo') == 1 && $gSettingsManager->getInt('photo_module_enabled') > 0) {
                $templateRow['roleRights'][] = array('icon' => 'bi bi-image-fill', 'title' => $gL10n->get('SYS_RIGHT_PHOTOS'));
            }
            if ($role->getValue('rol_documents_files') == 1 && $gSettingsManager->getInt('documents_files_module_enabled') > 0) {
                $templateRow['roleRights'][] = array('icon' => 'bi bi-file-earmark-arrow-down-fill', 'title' => $gL10n->get('SYS_RIGHT_DOCUMENTS_FILES'));
            }
            if ($role->getValue('rol_inventory_admin') == 1 && $gSettingsManager->getInt('inventory_module_enabled') > 0) {
                $templateRow['roleRights'][] = array('icon' => 'bi bi-box-seam-fill', 'title' => $gL10n->get('SYS_RIGHT_INVENTORY'));
            }
            if ($role->getValue('rol_forum_admin') == 1 && $gSettingsManager->getInt('forum_module_enabled') > 0) {
                $templateRow['roleRights'][] = array('icon' => 'bi bi-file-earmark-arrow-down-fill', 'title' => $gL10n->get('SYS_RIGHT_FORUM'));
            }
            if ($role->getValue('rol_weblinks') == 1 && $gSettingsManager->getInt('weblinks_module_enabled') > 0) {
                $templateRow['roleRights'][] = array('icon' => 'bi bi-link-45deg', 'title' => $gL10n->get('SYS_RIGHT_WEBLINKS'));
            }

            switch ($role->getValue('rol_mail_this_role')) {
                case 0:
                    $templateRow['emailToThisRole'] = $gL10n->get('SYS_NOBODY');
                    break;
                case 1:
                    $templateRow['emailToThisRole'] = $gL10n->get('SYS_ROLE_MEMBERS');
                    break;
                case 2:
                    $templateRow['emailToThisRole'] = $gL10n->get('ORG_REGISTERED_USERS');
                    break;
                case 3:
                    $templateRow['emailToThisRole'] = $gL10n->get('SYS_ALSO_VISITORS');
                    break;
            }

            switch ($role->getValue('rol_view_memberships')) {
                case 0:
                    $templateRow['viewMembership'] = $gL10n->get('SYS_NOBODY');
                    break;
                case 1:
                    $templateRow['viewMembership'] = $gL10n->get('SYS_ROLE_MEMBERS');
                    break;
                case 2:
                    $templateRow['viewMembership'] = $gL10n->get('ORG_REGISTERED_USERS');
                    break;
                case 3:
                    $templateRow['viewMembership'] = $gL10n->get('SYS_LEADERS');
                    break;
            }

            switch ($role->getValue('rol_view_members_profiles')) {
                case 0:
                    $templateRow['viewMembersProfiles'] = $gL10n->get('SYS_NOBODY');
                    break;
                case 1:
                    $templateRow['viewMembersProfiles'] = $gL10n->get('SYS_ROLE_MEMBERS');
                    break;
                case 2:
                    $templateRow['viewMembersProfiles'] = $gL10n->get('ORG_REGISTERED_USERS');
                    break;
                case 3:
                    $templateRow['viewMembersProfiles'] = $gL10n->get('SYS_LEADERS');
                    break;
            }

            switch ($role->getValue('rol_leader_rights')) {
                case 0:
                    $templateRow['roleLeaderRights'] = $gL10n->get('SYS_NO_ADDITIONAL_RIGHTS');
                    break;
                case 1:
                    $templateRow['roleLeaderRights'] = $gL10n->get('SYS_ASSIGN_MEMBERS');
                    break;
                case 2:
                    $templateRow['roleLeaderRights'] = $gL10n->get('SYS_EDIT_MEMBERS');
                    break;
                case 3:
                    $templateRow['roleLeaderRights'] = $gL10n->get('SYS_ASSIGN_EDIT_MEMBERS');
                    break;
            }

            $templateRow['actions'][] = array(
                'url' => SecurityUtils::encodeUrl(ADMIDIO_URL . FOLDER_MODULES . '/groups-roles/lists_show.php', array('mode' => 'html', 'role_list' => $row['rol_uuid'])),
                'icon' => 'bi bi-card-list',
                'tooltip' => $gL10n->get('SYS_SHOW_ROLE_MEMBERSHIP')
            );
            if ($roleType === $this::ROLE_TYPE_INACTIVE && !$role->getValue('rol_administrator')) {
                $templateRow['actions'][] = array(
                    'dataHref' => 'callUrlHideElement(\'role_' . $row['rol_uuid'] . '\', \'' . SecurityUtils::encodeUrl(ADMIDIO_URL . FOLDER_MODULES . '/groups-roles/groups_roles.php', array('mode' => 'activate', 'role_uuid' => $row['rol_uuid'])) . '\', \'' . $gCurrentSession->getCsrfToken() . '\')',
                    'dataMessage' => $gL10n->get('SYS_ACTIVATE_ROLE_DESC', array($row['rol_name'])),
                    'icon' => 'bi bi-eye',
                    'tooltip' => $gL10n->get('SYS_ACTIVATE_ROLE')
                );
            } elseif ($roleType === $this::ROLE_TYPE_ACTIVE && !$role->getValue('rol_administrator')) {
                $templateRow['actions'][] = array(
                    'dataHref' => 'callUrlHideElement(\'role_' . $row['rol_uuid'] . '\', \'' . SecurityUtils::encodeUrl(ADMIDIO_URL . FOLDER_MODULES . '/groups-roles/groups_roles.php', array('mode' => 'deactivate', 'role_uuid' => $row['rol_uuid'])) . '\', \'' . $gCurrentSession->getCsrfToken() . '\')',
                    'dataMessage' => $gL10n->get('SYS_DEACTIVATE_ROLE_DESC', array($row['rol_name'])),
                    'icon' => 'bi bi-eye-slash',
                    'tooltip' => $gL10n->get('SYS_DEACTIVATE_ROLE')
                );
            }
            if (!$role->getValue('rol_administrator')) {
                $templateRow['actions'][] = array(
                    'dataHref' => 'callUrlHideElement(\'role_' . $row['rol_uuid'] . '\', \'' . SecurityUtils::encodeUrl(ADMIDIO_URL . FOLDER_MODULES . '/groups-roles/groups_roles.php', array('mode' => 'delete', 'role_uuid' => $row['rol_uuid'])) . '\', \'' . $gCurrentSession->getCsrfToken() . '\')',
                    'dataMessage' => $gL10n->get('SYS_WANT_DELETE_ENTRY', array($row['rol_name'])),
                    'icon' => 'bi bi-trash',
                    'tooltip' => $gL10n->get('SYS_DELETE_ROLE')
                );
            }
            $templateData[] = $templateRow;
        }

        // initialize and set the parameter for DataTables
        $dataTables = new DataTables($this, 'adm_role_permissions_table');
        $dataTables->setGroupColumn(1);
        $dataTables->disableColumnsSort(array(3, 8));
        $dataTables->setColumnsNotHideResponsive(array(8));
        $dataTables->createJavascript(count($data), 7);

        $this->smarty->assign('list', $templateData);
        $this->smarty->assign('l10n', $gL10n);
        $this->pageContent .= $this->smarty->fetch('modules/groups-roles.permissions-list.tpl');
    }

    /**
     * Create content that is used on several pages and could be called in other methods. It will
     * create a function menu and a filter navbar.
     * @param string $categoryUUID UUID of the category for which the roles should be shown.
     * @param string $roleType The type of roles that should be shown within this page.
     *                         0 - inactive roles
     *                         1 - active roles
     *                         2 - event participation roles
     * @param string $mode The purpose of the current page. One of: 'cards', 'permissions', 'edit'
     *
     * @return void
     * @throws Exception
     */
    protected function createSharedHeader(string $categoryUUID, string $roleType, string $mode = 'cards'): void
    {
        global $gCurrentUser, $gSettingsManager, $gL10n, $gDb;

        if ($gCurrentUser->isAdministratorRoles()) {
            // show a link to create a new role
            $this->addPageFunctionsMenuItem(
                'menu_item_groups_roles_add',
                $gL10n->get('SYS_CREATE_ROLE'),
                ADMIDIO_URL . FOLDER_MODULES . '/groups-roles/groups_roles.php?mode=edit',
                'bi-plus-circle-fill'
            );

            if ($mode == 'cards') {
                // show permissions of all roles
                $this->addPageFunctionsMenuItem(
                    'menu_item_groups_roles_show_permissions',
                    $gL10n->get('SYS_SHOW_PERMISSIONS'),
                    SecurityUtils::encodeUrl(ADMIDIO_URL . FOLDER_MODULES . '/groups-roles/groups_roles.php', array('mode' => 'permissions', 'cat_uuid' => $categoryUUID, 'role_type' => $roleType)),
                    'bi-shield-lock-fill'
                );
            }

            $logShowTable = 'roles';
            if ($mode == 'cards') {
                $logShowTable = 'members';
            } elseif ($mode == 'permissions') {
                $logShowTable = 'roles_rights_data';
            }
            ChangelogService::displayHistoryButton($this, 'members', $logShowTable);

            // show a link to maintain categories
            $this->addPageFunctionsMenuItem(
                'menu_item_groups_roles_maintain_categories',
                $gL10n->get('SYS_EDIT_CATEGORIES'),
                SecurityUtils::encodeUrl(ADMIDIO_URL . FOLDER_MODULES . '/categories.php', array('type' => 'ROL')),
                'bi-hdd-stack-fill'
            );
        }

        // show a link to create an own list
        if ($gSettingsManager->getInt('groups_roles_edit_lists') === 1 // everyone
            || ($gSettingsManager->getInt('groups_roles_edit_lists') === 2 && $gCurrentUser->checkRolesRight('rol_edit_user')) // users with the right to edit all profiles
            || ($gSettingsManager->getInt('groups_roles_edit_lists') === 3 && $gCurrentUser->isAdministrator())) {
            $this->addPageFunctionsMenuItem(
                'menu_item_groups_own_list',
                $gL10n->get('SYS_CONFIGURE_LISTS'),
                ADMIDIO_URL . FOLDER_MODULES . '/groups-roles/mylist.php',
                'bi-card-list'
            );
        }

        // add filter navbar
        $this->addJavascript('
            $("#cat_uuid").change(function() {
                $("#adm_navbar_filter_form").submit();
            });
            $("#role_type").change(function() {
                $("#adm_navbar_filter_form").submit();
            });',
            true
        );

        // create a filter menu with elements for category
        $form = new FormPresenter(
            'adm_navbar_filter_form',
            'sys-template-parts/form.filter.tpl',
            ADMIDIO_URL . FOLDER_MODULES . '/groups-roles/groups_roles.php',
            $this,
            array('type' => 'navbar', 'setFocus' => false)
        );
        $form->addInput('mode', '', ($mode), array('property' => FormPresenter::FIELD_HIDDEN));
        $form->addSelectBoxForCategories(
            'cat_uuid',
            $gL10n->get('SYS_CATEGORY'),
            $gDb,
            'ROL',
            FormPresenter::SELECT_BOX_MODUS_FILTER,
            array('defaultValue' => $categoryUUID)
        );
        if ($gCurrentUser->isAdministratorRoles()) {
            $form->addSelectBox(
                'role_type',
                $gL10n->get('SYS_ROLE_TYPES'),
                array(0 => $gL10n->get('SYS_INACTIVE_GROUPS_ROLES'), 1 => $gL10n->get('SYS_ACTIVE_GROUPS_ROLES'), 2 => $gL10n->get('SYS_ROLES_CONFIRMATION_OF_PARTICIPATION')),
                array('defaultValue' => $roleType)
            );
        }
        $form->addToHtmlPage();
    }
}
