<?php

use idoit\Module\CustomFields\PropertyTypes;

/**
 * i-doit
 *
 * Custom fields attribute configuration popup.
 */
class isys_popup_custom_fields_attribute_configuration extends isys_component_popup
{
    /**
     * @var isys_component_database
     */
    protected $database;

    /**
     * @var isys_component_template_language_manager
     */
    protected $language;

    /**
     * @var isys_component_template
     */
    protected $template;

    /**
     * @param isys_component_template $template
     * @param                         $parameters
     *
     * @return void
     */
    public function handle_smarty_include(isys_component_template &$template, $parameters)
    {
        // Not necessary, will be triggered by JS directly.
    }

    /**
     * Method for handling the module request.
     *
     * @param isys_module_request $request
     *
     * @return isys_component_template|void
     * @throws \idoit\Exception\JsonException
     */
    public function &handle_module_request(isys_module_request $request)
    {
        $configuration = isys_format_json::decode($request->get_post('configuration'));

        $dialogFields = $this->retrieveDialogFields(isys_format_json::decode($request->get_post('otherProperties')), (string)$configuration['key']);

        $rules = [
            'field_type'              => [
                'p_arData'        => $this->getPropertyTypeData(),
                'p_bDbFieldNN'    => true,
                'p_strSelectedID' => $configuration['configValue'] ?? 'f_text',
                'p_strClass'      => 'input-small',
            ],
            'field_title'             => [
                'p_strValue' => $configuration['title'],
                'p_strClass' => 'input-small'
            ],
            'field_title_multiline'   => [
                'p_strValue'        => $configuration['title'],
                'p_strClass'        => 'input-block hide',
                'p_strStyle'        => 'resize:vertical;',
                'p_bInfoIconSpacer' => 0,
                'keepHtml'          => true,
                'disableInputGroup' => true
            ],
            'field_identifier' => [
                'p_strValue'       => $configuration['identifier'],
                'p_strClass'       => 'input-small hide',
                'p_strPlaceholder' => 'LC__SYSTEM__CUSTOM_CATEGORIES__FIELD_IDENTIFIER'
            ],
            'field_dialog_default'    => [
                'p_arData'        => [$configuration['default'] => 'empty'], // Necessary, because the frontend will fill the select.
                'p_bDbFieldNN'    => true,
                'p_strSelectedID' => $configuration['default'],
                'p_strClass'      => 'input-small hide'
            ],
            'field_relation'          => [
                'p_arData'        => $this->getRelationData(),
                'p_bDbFieldNN'    => true,
                'p_strSelectedID' => $configuration['identifier'],
                'p_strClass'      => 'input-small hide'
            ],
            'field_visibility'        => [
                'p_arData'        => $this->getVisibilityData(),
                'p_bSort'         => false,
                'p_bDbFieldNN'    => true,
                'p_strSelectedID' => $configuration['visibility'],
                'p_strClass'      => 'input-small'
            ],
            'field_dialog_dependency' => [
                'p_arData'        => $this->getDialogDependency(),
                'p_bSort'         => false,
                'p_bDbFieldNN'    => true,
                'p_strSelectedID' => $configuration['dialogDependency'] ?? -1,
                'p_strClass'      => 'input-small'
            ],
            'field_dialog_linked_to'  => [
                'p_arData'        => $dialogFields,
                'p_strSelectedID' => $configuration['dialogLinkedTo'],
                'p_strClass'      => 'input-small'
            ]
        ];

        if (isset($configuration['disable']) && $configuration['disable']) {
            $rules['field_type']['p_arDisabled'] = array_fill_keys(array_keys($rules['field_type']['p_arData']), true);
            $rules['field_type']['p_strClass'] .= ' disabled';
        }

        $ajaxUrl = isys_helper_link::create_url([
            C__CMDB__GET__POPUP  => 'custom_fields_attribute_configuration',
            C__GET__AJAX_REQUEST => 'handle_ajax_request',
        ], true);

        $this->template->activate_editmode()
            ->assign('ajax_url', $ajaxUrl)
            ->assign('key', $configuration['key'])
            ->assign('propertyTitle', substr($configuration['title'], 0, 75))
            ->assign('dialogYesNoDefaults', $this->getDialogYesNoDefaults())
            ->assign('calendarDefaults', $this->getCalendarDefaults())
            ->assign('singleLineFields', $this->getSingleLineFields())
            ->assign('isMultivalueCategory', (bool)$request->get_post('multivalued'))
            ->assign('showInLine', (bool)$configuration['show_in_list'])
            ->smarty_tom_add_rules('tom.popup.custom-fields', $rules)
            ->display(isys_module_custom_fields::getPath() . 'templates/popup/attribute-configuration.tpl');
        die;
    }

    /**
     * @param array $properties
     *
     * @return array
     */
    private function retrieveDialogFields(array $properties, string $excludeKey): array
    {
        $values = [];

        foreach ($properties as $property) {
            // Skip non disabled fields, because they have not yet been saved.
            if (!isset($property['disable']) || !$property['disable']) {
                continue;
            }

            // Skip "itself" and other fields that are not dialog+.
            if ($property['key'] !== $excludeKey && $property['type'] === 'f_popup' && $property['popup'] === 'dialog_plus' && !$property['multiselection']) {
                $values[$property['key']] = $property['title'];
            }
        }

        return $values;
    }

    /**
     * @return string[]
     */
    private function getPropertyTypeData(): array
    {
        $values = [];
        $propertyTypes = PropertyTypes::getAll($this->language);

        foreach ($propertyTypes as $type) {
            $values[$type['configValue']] = $type['title'];
        }

        return $values;
    }

    /**
     * Get all field types, that are "single line" only (= not allowed to share the same row).
     *
     * @return string[]
     */
    private function getSingleLineFields(): array
    {
        $types = PropertyTypes::getAll($this->language);

        return array_values(array_map(function ($type) {
            return $type['configValue'];
        }, array_filter(PropertyTypes::getAll($this->language), function ($type) {
            return !$type[PropertyTypes::ALLOW_INLINE];
        })));
    }

    /**
     * @return string[]
     */
    private function getRelationData(): array
    {
        $values = [];
        $relationTypeData = isys_cmdb_dao_category_g_relation::instance($this->database)
            ->get_relation_types_as_array(null);

        foreach ($relationTypeData as $relationTypeId => $relationType) {
            $values[$relationTypeId] = $relationType['title_lang'];
        }

        return $values;
    }

    /**
     * @return string[]
     */
    private function getVisibilityData(): array
    {
        return [
            'visible'  => 'LC__SYSTEM__CUSTOM_CATEGORIES__FIELD_HANDLING__STANDARD',
            'readonly' => 'LC__SYSTEM__CUSTOM_CATEGORIES__FIELD_HANDLING__API_ONLY',
            'hidden'   => 'LC__SYSTEM__CUSTOM_CATEGORIES__FIELD_HANDLING__HIDDEN'
        ];
    }

    /**
     * @return string[]
     */
    private function getDialogDependency(): array
    {
        return [
            -1                                  => 'LC__SYSTEM__CUSTOM_CATEGORIES__DEPENDENCY__NONE',
            PropertyTypes::DEPENDENCY_PRIMARY   => 'LC__SYSTEM__CUSTOM_CATEGORIES__DEPENDENCY__PRIMARY',
            PropertyTypes::DEPENDENCY_SECONDARY => 'LC__SYSTEM__CUSTOM_CATEGORIES__DEPENDENCY__SECONDARY'
        ];
    }

    /**
     * @return string[]
     */
    private function getDialogYesNoDefaults(): array
    {
        return [
            -1 => $this->language->get('LC__SYSTEM__CUSTOM_CATEGORIES__DEFAULT_NONE'),
            1  => $this->language->get('LC__SYSTEM__CUSTOM_CATEGORIES__DEFAULT_YES'),
            0  => $this->language->get('LC__SYSTEM__CUSTOM_CATEGORIES__DEFAULT_NO')
        ];
    }

    /**
     * @return string[]
     */
    private function getCalendarDefaults(): array
    {
        return [
            1  => $this->language->get('LC__SYSTEM__CUSTOM_CATEGORIES__CALENDAR_WITH_TIME'),
            -1 => $this->language->get('LC__SYSTEM__CUSTOM_CATEGORIES__CALENDAR_WITHOUT_TIME')
        ];
    }

    /**
     * Constructor method.
     *
     * @throws Exception
     */
    public function __construct()
    {
        parent::__construct();

        $this->database = isys_application::instance()->container->get('database');
        $this->template = isys_application::instance()->container->get('template');
        $this->language = isys_application::instance()->container->get('language');
    }
}
