<?php

/**
 * CMDB Tree view for object types
 *
 * @package     i-doit
 * @subpackage  CMDB_Views
 * @author      Andre Woesten <awoesten@i-doit.de>
 * @version     Dennis Stücken <dstuecken@i-doit.org>
 * @version     1.0
 * @copyright   synetics GmbH
 * @license     http://www.gnu.org/licenses/agpl-3.0.html GNU AGPLv3
 */
class isys_cmdb_view_tree_objecttype extends isys_cmdb_view_tree
{
    /**
     * Returns the view mode ID
     *
     * @return integer
     */
    public function get_id()
    {
        return C__CMDB__VIEW__TREE_OBJECTTYPE;
    }

    /**
     *
     * @param  array &$l_gets
     */
    public function get_mandatory_parameters(&$l_gets)
    {
        parent::get_mandatory_parameters($l_gets);
    }

    /**
     * @return string
     */
    public function get_name()
    {
        return "Objekttypbaum";
    }

    /**
     *
     * @param  array &$l_gets
     */
    public function get_optional_parameters(&$l_gets)
    {
        parent::get_optional_parameters($l_gets);

        $l_gets[C__CMDB__GET__OBJECTGROUP] = true;
    }

    /**
     * Method for building the object type tree.
     */
    public function tree_build()
    {
        global $g_config, $g_dirs;

        $language = isys_application::instance()->container->get('language');
        $displayCounter = (bool)isys_tenantsettings::get('cmdb.gui.display-object-type-counter', 1);

        $l_gets = $this->get_module_request()->get_gets();
        $l_dao = $this->get_dao_cmdb();
        $l_tpl = $this->get_module_request()->get_template();

        $this->remove_ajax_parameters($l_gets);

        // Set default object group, if unset.
        if (isset($l_gets[C__CMDB__GET__OBJECTTYPE])) {
            $l_gets[C__CMDB__GET__OBJECTGROUP] = $l_dao->retrieve('SELECT isys_obj_type__isys_obj_type_group__id FROM isys_obj_type WHERE isys_obj_type__id = ' .
                $l_dao->convert_sql_id($l_gets[C__CMDB__GET__OBJECTTYPE]) . ';')
                ->get_row_value('isys_obj_type__isys_obj_type_group__id');
        } elseif (!isset($l_gets[C__CMDB__GET__OBJECTGROUP])) {
            $l_gets[C__CMDB__GET__OBJECTGROUP] = $l_dao->retrieve('SELECT isys_obj_type_group__id FROM isys_obj_type_group WHERE isys_obj_type_group__status = ' .
                $l_dao->convert_sql_int(C__RECORD_STATUS__NORMAL) . ' ORDER BY isys_obj_type_group__sort ASC LIMIT 0,1;')
                ->get_row_value('isys_obj_type_group__id');
        }

        // Determines types for the specified object type group.
        $l_typeres = $l_dao->objtype_get_by_objgroup_id($l_gets[C__CMDB__GET__OBJECTGROUP], true, C__RECORD_STATUS__NORMAL, $displayCounter);

        /**
         * This is specifically needed for the new CREATE right for object types.
         * We're initially receiving all allowed object types, and then attach them to the tree, if the user does not have any objects in them.
         * That will allow creating an object type.
         */
        $l_object_type_auth = isys_auth_cmdb_object_types::instance();
        $l_allowed_object_types = $l_object_type_auth->get_allowed_objecttypes(isys_auth::CREATE);

        // Add root node.
        $l_rootgets = $l_gets;
        $l_rootgets[C__CMDB__GET__VIEWMODE] = C__CMDB__VIEW__LIST_OBJECTTYPE;

        $l_groupres = $l_dao->objgroup_get_by_id($l_gets[C__CMDB__GET__OBJECTGROUP]);

        if (count($l_groupres)) {
            $l_groupdata = $l_groupres->get_row();
            $l_roottitle = $language->get($l_groupdata["isys_obj_type_group__title"]);
        } else {
            $l_roottitle = $language->get('LC__CMDB__OBJTYPE');
        }

        $l_root_link = isys_glob_build_ajax_url(C__FUNC__AJAX__CONTENT_BY_OBJECT_GROUP, $l_rootgets);

        $l_root = $this->m_tree->add_node(
            0,
            C__CMDB__TREE_NODE__PARENT,
            $l_roottitle,
            $l_root_link,
            '',
            $g_dirs['images'] . 'axialis/user-interface/interface-3-filled.svg',
            false,
            '',
            '',
            true,
            'mb5'
        );

        $l_objtypeid = $l_gets[C__CMDB__GET__OBJECTTYPE];

        // We want an object list and a type tree.
        $l_gets[C__CMDB__GET__VIEWMODE] = C__CMDB__VIEW__LIST_OBJECT;
        $l_gets[C__CMDB__GET__TREEMODE] = C__CMDB__VIEW__TREE_OBJECTTYPE;

        $l_type_data_arr = [];

        while ($l_typedata = $l_typeres->get_row()) {
            // If the user is allowed to see this object types because he has objects in it, remove it from the allowed object types array, so it
            // does not get added to the tree twice.
            if (isset($l_allowed_object_types[$l_typedata['isys_obj_type__id']])) {
                unset($l_allowed_object_types[$l_typedata['isys_obj_type__id']]);
            }

            if (empty($l_typedata["isys_obj_type__show_in_tree"])) {
                continue;
            }

            $l_type_data_arr[$language->get($l_typedata['isys_obj_type__title']) . $l_typedata['isys_obj_type__id']] = $l_typedata;
        }

        $l_dao_object_types = \idoit\Module\Cmdb\Model\CiTypeCache::instance(isys_application::instance()->container->get('database'));

        /**
         * Assign additional object types to l_type_data_arr that are coming from a create right on these types
         */
        if (is_array($l_allowed_object_types) && !empty($l_allowed_object_types)) {
            // Get object counts which we could not retrieve in previous query

            $countSelect = "''";

            if ($displayCounter) {
                $countSelect = '(SELECT COUNT(isys_obj__id)
                    FROM isys_obj WHERE isys_obj__status = ' . $l_dao->convert_sql_int(C__RECORD_STATUS__NORMAL) . '
                    AND isys_obj__isys_obj_type__id = isys_obj_type__id
                    ' . isys_auth_cmdb_objects::instance()->get_allowed_objects_condition(isys_auth::VIEW) . ')';
            }

            $l_objCountSql = 'SELECT isys_obj_type__id, ' . $countSelect . ' AS objectCount
                FROM isys_obj_type
                WHERE isys_obj_type__id IN (' . implode(',', $l_allowed_object_types) . ')';

            $l_resObjCount = $l_dao->retrieve($l_objCountSql);
            $l_objCountForTypes = [];
            while ($l_rowObjCount = $l_resObjCount->get_row()) {
                $l_objCountForTypes[$l_rowObjCount['isys_obj_type__id']] = $l_rowObjCount['objectCount'];
            }

            foreach ($l_allowed_object_types as $l_object_type_id) {
                $l_object_type = $l_dao_object_types->get($l_object_type_id);

                if ($l_object_type->groupId == $l_gets[C__CMDB__GET__OBJECTGROUP]) {
                    $l_object_type_temp = $l_object_type->toArray($l_object_type->columnMap());
                    $l_object_type_temp['objcount'] = $l_objCountForTypes[$l_object_type_id];

                    $l_type_data_arr[$language->get($l_object_type->title) . $l_object_type->id] = $l_object_type_temp;
                }
            }
            unset($l_object_type_temp);
        }

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

        if ($objectTypeSorting == C__CMDB__VIEW__OBJECTTYPE_SORTING__AUTOMATIC && count($l_type_data_arr)) {
            ksort($l_type_data_arr);
        }

        foreach ($l_type_data_arr as $l_typedata) {
            $l_icon = "";

            if (empty($l_typedata["isys_obj_type__show_in_tree"])) {
                continue;
            }

            $l_issel = $l_typedata["isys_obj_type__id"] == $l_objtypeid;

            $l_gets[C__CMDB__GET__OBJECTTYPE] = $l_typedata["isys_obj_type__id"];

            if (!empty($l_typedata["isys_obj_type__icon"])) {
                if (strstr($l_typedata["isys_obj_type__icon"], '/')) {
                    $l_icon = $g_config['www_dir'] . $l_typedata["isys_obj_type__icon"];
                } else {
                    $l_icon = $g_dirs["images"] . "tree/" . $l_typedata["isys_obj_type__icon"];
                }
            }

            $l_link = "javascript:tree_obj_type_click('" . $l_typedata["isys_obj_type__id"] . "');";
            $l_title = isys_glob_escape_string(isys_helper::sanitize_text($language->get($l_dao->get_objtype_name_by_id_as_string($l_typedata["isys_obj_type__id"]))));

            if ($displayCounter) {
                $nodeLabel = '<span' . ($l_typedata["objcount"] > 0 ? '' : ' class="obj_noentries"') . '>' . $l_title . '</span> <span>(' . $l_typedata["objcount"] . ')</span>';
            } else {
                $nodeLabel = '<span>' . $l_title . '</span> <span class="hide">(1)</span>';
            }


            $this->m_tree->add_node(
                $l_typedata["isys_obj_type__id"],
                $l_root,
                $nodeLabel,
                $l_link,
                '',
                $l_icon,
                $l_issel,
                '',
                '',
                true,
                $l_typedata["isys_obj_type__const"]
            );
        }

        $userSettings = isys_application::instance()->container->get('settingsUser');

        $l_tpl->assign('treeHide', (int)$userSettings->get('gui.tree.hide-empty-object-types', false));

        $this->m_tree->set_tree_sort(false);

        // Sets the eye for hiding empty nodes
        $this->m_tree->set_tree_visibility(true);

        isys_component_signalcollection::get_instance()
            ->emit("mod.cmdb.extendObjectTypeTree", $this->m_tree);
    }

    /**
     *
     * @return  string
     */
    public function tree_process()
    {
        $l_proc = '';

        if (defined("C__OBJECT_DRAGNDROP") && C__OBJECT_DRAGNDROP) {
            $message = isys_application::instance()->container->get('language')->get('LC__CMDB__TREE_VIEW__OBJECTTYPE__DROP_OBJECTS_CONFIRM');
            $l_proc = "init_drops({ confirmMessage:'{$message}' });";
        }

        return $this->m_tree
            ->set_tree_search(true)
            ->process(null, $l_proc);
    }
}
