<?php

/**
 * AJAX
 *
 * @package     i-doit
 * @subpackage  General
 * @author      Van Quyen Hoang <qhoang@i-doit.org>
 * @version     1.0
 * @copyright   synetics GmbH
 * @license     http://www.i-doit.com/license
 * @since       1.0
 */
class isys_ajax_handler_quick_configuration_wizard extends isys_ajax_handler
{
    /**
     * Init method, which gets called from the framework.
     *
     * @global  isys_component_database $g_comp_database
     * @author  Van Quyen Hoang <qhoang@i-doit.org>
     * @author  Leonard Fischer <lfischer@i-doit.org>
     */
    public function init()
    {
        // We set the header information because we don't accept anything than JSON.
        header('Content-Type: application/json');

        $l_return = [];
        $l_module = new isys_module_quick_configuration_wizard();
        $l_dao = isys_quick_configuration_wizard_dao::instance(isys_application::instance()->container->get('database'));
        $language = isys_application::instance()->container->get('language');

        if (isset($_GET['func'])) {
            $l_return = [
                'success' => true,
                'data'    => null,
                'message' => ''
            ];

            try {
                isys_module_system::getAuth()->check(isys_auth::VIEW, 'GLOBALSETTINGS/QCW');

                switch ($_GET['func']) {
                    case 'sortObjectTypeGroups':
                        isys_module_system::getAuth()->check(isys_auth::EXECUTE, 'GLOBALSETTINGS/QCW');
                        $l_return['data'] = $l_dao->update_object_type_group_sorting($_POST['sorting']);
                        break;

                    case 'hideObjectTypeGroup':
                        isys_module_system::getAuth()->check(isys_auth::EXECUTE, 'GLOBALSETTINGS/QCW');

                        if (!defined($_POST['objectTypeGroupConst'])) {
                            throw new isys_exception_general('The given object type group constant ("' . $_POST['objTypeGroup'] . '") does not exist.');
                        }

                        $l_return['data'] = $l_dao->hide_object_type_gorup(constant($_POST['objectTypeGroupConst']));
                        break;

                    case 'loadAssignedObjectTypesByGroup':
                        if (!defined($_POST['objectTypeGroupConst'])) {
                            throw new isys_exception_general('The given object type group constant ("' . $_POST['objectTypeGroupConst'] . '") does not exist.');
                        }

                        $l_return['data'] = $l_dao->load_assigned_object_types_by_group(constant($_POST['objectTypeGroupConst']));
                        break;

                    case 'sortObjectTypes':
                        isys_module_system::getAuth()->check(isys_auth::EXECUTE, 'GLOBALSETTINGS/QCW');

                        $l_return['data'] = $l_dao->update_object_type_sorting($_POST['sorting']);
                        break;

                    case 'loadAssignedCategoriesByObjectTypes':
                        if (!defined($_POST['objectTypeConst'])) {
                            throw new isys_exception_general('The given object type constant ("' . $_POST['objectTypeConst'] . '") does not exist.');
                        }

                        $l_return['data'] = $l_dao->load_assigned_categories_by_object_type(constant($_POST['objectTypeConst']));
                        break;

                    case 'detachObjectTypeFromGroup':
                        isys_module_system::getAuth()->check(isys_auth::EXECUTE, 'GLOBALSETTINGS/QCW');

                        if (!defined($_POST['objectTypeConst'])) {
                            throw new isys_exception_general('The given object type constant ("' . $_POST['objectTypeConst'] . '") does not exist.');
                        }

                        $l_return['data'] = $l_dao->detach_object_type_from_group(constant($_POST['objectTypeConst']));
                        break;

                    case 'detachCategoryFromObjectType':
                        isys_module_system::getAuth()->check(isys_auth::EXECUTE, 'GLOBALSETTINGS/QCW');

                        if (!defined($_POST['objectTypeConst']) || !defined($_POST['categoryConst'])) {
                            throw new isys_exception_general('The given category- and/or object type constant ("' . $_POST['categoryConst'] . '" and ' .
                                $_POST['objectTypeConst'] . '") do not exist.');
                        }

                        $l_return['data'] = $l_dao->detach_category_from_object_type(
                            constant($_POST['categoryConst']),
                            constant($_POST['objectTypeConst']),
                            !!$_POST['customCategory']
                        );
                        break;

                    case 'loadObjectTypeGroups':
                        $l_return['data'] = [];
                        $l_result = \idoit\Module\QCW\Model\ObjectTypeGroup::instance($this->m_database_component)
                            ->load();

                        if (count($l_result)) {
                            while ($l_row = $l_result->get_row()) {
                                $l_return['data'][] = [
                                    'title'       => $language->get($l_row['isys_obj_type_group__title']),
                                    'constant'    => $l_row['isys_obj_type_group__const'],
                                    'selfdefined' => !(strpos($l_row['isys_obj_type_group__const'], 'C__OBJTYPE_GROUP__SD_') === false),
                                    'active'      => !($l_row['isys_obj_type_group__status'] == 1)
                                ];
                            }
                        }

                        break;

                    case 'loadObjectTypes':
                        $l_cnt = 0;
                        $l_return['data'] = [];
                        $l_result = \idoit\Module\QCW\Model\ObjectType::instance($this->m_database_component)
                            ->load(null, true);

                        if (count($l_result)) {
                            while ($l_row = $l_result->get_row()) {
                                $l_return['data'][str_pad($l_row['isys_obj_type__sort'] ?? '', 3, '0', STR_PAD_LEFT) . '-' . $l_cnt] = [
                                    'title'       => $language->get($l_row['isys_obj_type__title']),
                                    'count'       => ($l_row['count'] ?: 0),
                                    'constant'    => $l_row['isys_obj_type__const'],
                                    'selfdefined' => (bool)$l_row['isys_obj_type__selfdefined'],
                                    'color'       => isys_helper_color::unifyHexColor((string)($l_row['isys_obj_type__color'] ?? '#ffffff')),
                                    'orphaned'    => ((int)$l_row['isys_obj_type__isys_obj_type_group__id'] === C__OBJTYPE_GROUP__ORPHANED)
                                ];

                                $l_cnt++;
                            }
                        }

                        $objectTypeSorting = isys_tenantsettings::get('cmdb.registry.object_type_sorting', C__CMDB__VIEW__OBJECTTYPE_SORTING__AUTOMATIC);

                        // We check, if the object-types should be sorted by name (alphabetically) or manually.
                        if ($objectTypeSorting == C__CMDB__VIEW__OBJECTTYPE_SORTING__AUTOMATIC) {
                            usort($l_return['data'], 'isys_glob_array_compare_title');
                        } else {
                            ksort($l_return['data']);
                        }
                        break;

                    case 'loadCategories':
                        $l_return['data'] = [];
                        $l_result = \idoit\Module\QCW\Model\Category::instance($this->m_database_component)
                            ->loadGlobal();

                        if (count($l_result)) {
                            while ($l_row = $l_result->get_row()) {
                                $l_return['data'][] = [
                                    'title'       => $language->get($l_row['isysgui_catg__title']),
                                    'constant'    => $l_row['isysgui_catg__const'],
                                    'selfdefined' => false
                                ];
                            }
                        }

                        $l_result = \idoit\Module\QCW\Model\Category::instance($this->m_database_component)
                            ->loadCustom();

                        if (count($l_result)) {
                            while ($l_row = $l_result->get_row()) {
                                $l_return['data'][] = [
                                    'title'       => isys_glob_htmlentities($language->get($l_row['isysgui_catg_custom__title'])),
                                    'constant'    => $l_row['isysgui_catg_custom__const'],
                                    'selfdefined' => true
                                ];
                            }
                        }

                        usort($l_return['data'], 'isys_glob_array_compare_title');

                        break;
                }
            } catch (Exception $e) {
                $l_return['success'] = false;
                $l_return['message'] = $e->getMessage();
            }
        } else {
            try {
                switch ($_POST['func']) {
                    // Deletion and resetting.
                    case 'delete_file':
                        isys_module_system::getAuth()->check(isys_auth::EXECUTE, 'GLOBALSETTINGS/QCW');
                        $l_return = isys_module_quick_configuration_wizard::delete_config_file($_POST['file']);
                        break;

                    case 'reset':
                        isys_module_system::getAuth()->check(isys_auth::EXECUTE, 'GLOBALSETTINGS/QCW');
                        $l_return = $this->reset_configuration();
                        break;

                    case 'load_profiles':
                        isys_module_system::getAuth()->check(isys_auth::EXECUTE, 'GLOBALSETTINGS/QCW');
                        $l_selection = isys_format_json::decode($_POST['profile_files']);

                        if (count($l_selection) > 0) {
                            $l_caching = isys_caching::factory('objecttypeconfig');
                            try {
                                $l_module->load_config($l_selection, $l_caching);
                                $l_caching->clear();
                                isys_caching::factory()
                                    ->delete_all_except([
                                        'getdataconditionless',
                                        'validationconfig'
                                    ]);
                                // Recreate const_cache because maybe we got new objecttypes or categories
                                isys_component_constant_manager::instance()
                                    ->create_dcm_cache();
                                $l_return['success'] = true;
                            } catch (isys_exception_general $e) {
                                $l_return['success'] = false;
                            }
                        }
                        break;
                }
            } catch (Exception $e) {
                $l_return = [
                    'success' => false,
                    'message' => $e->getMessage()
                ];
            }
        }

        // We want to go sure, our changes will appear, so we clear the menu cache.
        isys_caching::factory()
            ->delete_all_except(['getdataconditionless', 'validationconfig']);

        echo isys_format_json::encode($l_return);

        $this->_die();
    }

    /**
     * Reset the configuration and set the object-type-groups to default visibility and sorting.
     *
     * @return  array
     * @author  Leonard Fischer
     */
    protected function reset_configuration()
    {
        $l_dao = isys_cmdb_dao::instance($this->m_database_component);

        $l_skipped_categories = isys_quick_configuration_wizard_dao::get_skipped_objecttypes();

        $l_skipped_categories_string = '"' . implode('","', $l_skipped_categories) . '"';

        // 1 - Remove all custom categories from all object types.
        if (!$l_dao->update('DELETE FROM isys_obj_type_2_isysgui_catg_custom WHERE TRUE;')) {
            return [
                'success' => false,
                'message' => isys_application::instance()->container->get('language')
                    ->get('LC__MODULE__QCW__RESET_ERROR__CUSTOM_CAT_ASSIGNMENT')
            ];
        }

        // 2 - Remove all global categories from all object types. But keep some necessary (global, relation, logbook, ...)
        $l_sql = 'DELETE isys_obj_type_2_isysgui_catg FROM isys_obj_type_2_isysgui_catg
			LEFT JOIN isysgui_catg ON isys_obj_type_2_isysgui_catg__isysgui_catg__id = isysgui_catg__id
			LEFT JOIN isys_obj_type ON isys_obj_type_2_isysgui_catg__isys_obj_type__id = isys_obj_type__id
			WHERE isysgui_catg__const NOT IN ("C__CATG__GLOBAL", "C__CATG__RELATION", "C__CATG__LOGBOOK", "C__CATG__MULTIEDIT")
			AND isys_obj_type__const NOT IN (' . $l_skipped_categories_string . ')';

        if (!$l_dao->update($l_sql)) {
            return [
                'success' => false,
                'message' => isys_application::instance()->container->get('language')
                    ->get('LC__MODULE__QCW__RESET_ERROR__GLOBAL_CAT_ASSIGNMENT')
            ];
        }

        // 3 - Remove all possible categories (without: global, relation, logbook, ...) from the overview.
        $l_sql = 'DELETE isys_obj_type_2_isysgui_catg_overview FROM isys_obj_type_2_isysgui_catg_overview
			LEFT JOIN isysgui_catg ON isysgui_catg.isysgui_catg__id = isys_obj_type_2_isysgui_catg_overview.isysgui_catg__id
			LEFT JOIN isys_obj_type ON isys_obj_type.isys_obj_type__id = isys_obj_type_2_isysgui_catg_overview.isys_obj_type__id
			WHERE isysgui_catg__const NOT IN ("C__CATG__GLOBAL", "C__CATG__RELATION", "C__CATG__LOGBOOK", "C__CATG__MULTIEDIT")
			AND isys_obj_type__const NOT IN (' . $l_skipped_categories_string . ')';

        if (!$l_dao->update($l_sql)) {
            return [
                'success' => false,
                'message' => isys_application::instance()->container->get('language')
                    ->get('LC__MODULE__QCW__RESET_ERROR__OVERVIEW_CAT_ASSIGNMENT')
            ];
        }

        // 4 - Remove all object types from all object type groups.
        $l_sql = 'UPDATE isys_obj_type
			SET isys_obj_type__isys_obj_type_group__id = NULL,
			isys_obj_type__status = ' . $l_dao->convert_sql_int(C__RECORD_STATUS__BIRTH) . ',
			isys_obj_type__show_in_tree = 0
			WHERE TRUE;';

        if (!$l_dao->update($l_sql)) {
            return [
                'success' => false,
                'message' => isys_application::instance()->container->get('language')
                    ->get('LC__MODULE__QCW__RESET_ERROR__OBJ_TYPE_ASSIGNMENT')
            ];
        }

        // 5 - Display no object type groups in the menu, but the "standards" (software, infrastructure, ...). Also reset the sorting.
        $l_sql = 'UPDATE isys_obj_type_group
			SET isys_obj_type_group__status = ' . $l_dao->convert_sql_int(C__RECORD_STATUS__BIRTH) . ',
			isys_obj_type_group__sort = isys_obj_type_group__id
			WHERE TRUE;';

        if (!$l_dao->update($l_sql)) {
            return [
                'success' => false,
                'message' => isys_application::instance()->container->get('language')
                    ->get('LC__MODULE__QCW__RESET_ERROR__OBJ_TYPE_GROUP_RESET')
            ];
        }

        $l_sql = 'UPDATE isys_obj_type_group
			SET isys_obj_type_group__status = ' . $l_dao->convert_sql_int(C__RECORD_STATUS__NORMAL) . '
			WHERE isys_obj_type_group__const IN ("C__OBJTYPE_GROUP__SOFTWARE", "C__OBJTYPE_GROUP__INFRASTRUCTURE", "C__OBJTYPE_GROUP__OTHER", "C__OBJTYPE_GROUP__CONTACT");';

        if (!$l_dao->update($l_sql)) {
            return [
                'success' => false,
                'message' => isys_application::instance()->container->get('language')
                    ->get('LC__MODULE__QCW__RESET_ERROR__OBJ_TYPE_GROUP_VISIBILITY')
            ];
        }

        return [
            'success' => true
        ];
    }
}
