<?php

/**
 * i-doit
 * Visualization profile model.
 *
 * @package     modules
 * @subpackage  pro
 * @author      Leonard Fischer <lfischer@i-doit.com>
 * @version     1.0
 * @copyright   synetics GmbH
 * @license     http://www.i-doit.com/license
 * @since       i-doit 1.5.0
 */
class isys_visualization_profile_model extends isys_component_dao
{
    /**
     * This variable will be used as internal content cache, when getting profile contents.
     *
     * @var  array
     */
    private $contentCache = [];

    /**
     * This array holds all available table fields. Use this for validation.
     *
     * @var  array
     */
    private $tableFields = [
        'isys_visualization_profile__id',
        'isys_visualization_profile__title',
        'isys_visualization_profile__const',
        'isys_visualization_profile__defaults',
        'isys_visualization_profile__obj_info_config',
        'isys_visualization_profile__config'
    ];

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

    /**
     * @var string
     */
    private $emptyValue;

    /**
     * isys_visualization_profile_model constructor.
     *
     * @param  isys_component_database $p_db
     *
     * @throws Exception
     */
    public function __construct(isys_component_database $p_db)
    {
        parent::__construct($p_db);

        $this->language = isys_application::instance()->container->get('language');
        $this->emptyValue = isys_tenantsettings::get('gui.empty_value', '-');
    }

    /**
     * Method for retrieving the profiles.
     *
     * @param   mixed $p_id May be an array or an integer.
     *
     * @return  isys_component_dao_result
     * @throws  Exception
     * @throws  isys_exception_database
     */
    public function get_profile($p_id = null)
    {
        $l_sql = 'SELECT * FROM isys_visualization_profile WHERE TRUE';

        if ($p_id !== null) {
            if (!is_array($p_id)) {
                $p_id = [$p_id];
            }

            $l_sql .= ' AND isys_visualization_profile__id ' . $this->prepare_in_condition($p_id);
        }

        return $this->retrieve($l_sql);
    }

    /**
     * Returns the bare profile configuration.
     *
     * @param   integer $p_id
     *
     * @return  array
     * @throws  Exception
     */
    public function get_profile_config($p_id)
    {
        if (!($p_id > 0)) {
            return [];
        }

        $l_profile = $this->get_profile($p_id)
            ->get_row();

        return isys_format_json::decode($l_profile['isys_visualization_profile__config']);
    }

    /**
     * @param   integer $p_id
     * @param   array   $p_data
     *
     * @return  boolean
     */
    public function save_profile($p_id = null, array $p_data = [])
    {
        $l_data = [];

        foreach ($p_data as $l_key => $l_value) {
            if (in_array($l_key, $this->tableFields, true)) {
                $l_data[] = $l_key . ' = ' . $this->convert_sql_text($l_value);
            }
        }

        if ($p_id > 0) {
            $l_sql = 'UPDATE isys_visualization_profile SET %s WHERE isys_visualization_profile__id = ' . $this->convert_sql_id($p_id) . ';';
        } else {
            $l_sql = 'INSERT INTO isys_visualization_profile SET %s;';
        }

        if (count($l_data)) {
            return $this->update(sprintf($l_sql, implode(', ', $l_data))) && $this->apply_update();
        }

        return false;
    }

    /**
     * Method for deleting a given profile.
     *
     * @param   integer $p_id
     * @param   boolean $p_force
     *
     * @return  boolean
     * @throws  Exception
     * @throws  isys_exception_database
     * @throws  isys_exception_general
     */
    public function delete_profile($p_id, $p_force = false)
    {
        $l_profile_const = $this->get_profile($p_id)
            ->get_row_value('isys_visualization_profile__const');

        if (!empty($l_profile_const) && !$p_force) {
            throw new isys_exception_general('This profile can not be deleted!');
        }

        return $this->update('DELETE FROM isys_visualization_profile WHERE isys_visualization_profile__id = ' . $this->convert_sql_id($p_id) . ';') && $this->apply_update();
    }

    /**
     * Method for duplicating a profile.
     *
     * @param   integer $p_id
     *
     * @return  integer
     * @throws  isys_exception_database
     */
    public function duplicate_profile($p_id)
    {
        $l_profile = $this->get_profile($p_id)
            ->get_row();

        $l_profile['isys_visualization_profile__title'] = $this->language->get('LC__VISUALIZATION_PROFILES__DUPLICATE') . ': ' .
            $this->language->get($l_profile['isys_visualization_profile__title']);

        // We don't need these two fields.
        unset($l_profile['isys_visualization_profile__id'], $l_profile['isys_visualization_profile__const']);

        if ($this->save_profile(null, $l_profile)) {
            return $this->get_last_insert_id();
        }

        throw new isys_exception_database($this->m_last_error);
    }

    /**
     * Method for getting profile option content.
     *
     * @param   isys_tree|isys_tree_node $p_node
     * @param   string                   $p_option
     *
     * @return  mixed
     */
    public function get_profile_options_content($p_node, $p_option)
    {
        $l_node_data = $p_node->get_data();
        $key = $l_obj_id = $l_node_data['data']['obj_id'];

        if ($l_node_data['data']['obj_type_id'] == -1) {
            // Objects with "obj_type_id" == -1 are doubled objects. They need no data.
            return null;
        }

        // @see  ID-5090  Append the relation object id to the cache key.
        if ($l_node_data['data']['relation_obj_id'] !== null) {
            $key .= '-' . $l_node_data['data']['relation_obj_id'];
        }

        if (isset($this->contentCache[$key]) && isset($this->contentCache[$key][$p_option])) {
            // @see  ID-5232  If we are displaying the relation type, we can't use the cache.
            if ($p_option === C__VISUALIZATION_PROFILE__RELATION_TYPE && $l_node_data['data']['relation_obj_id']) {
                return $this->language->get(isys_cmdb_dao_category_s_relation_details::instance($this->m_db)
                        ->get_data(null, $l_node_data['data']['relation_obj_id'])
                        ->get_row_value('isys_relation_type__title'));
            }

            return $this->contentCache[$key][$p_option];
        }

        $l_return = null;

        switch ($p_option) {
            default:
            case C__VISUALIZATION_PROFILE__OBJ_TITLE:
                $l_return = $l_node_data['data']['obj_title'];
                break;

            case C__VISUALIZATION_PROFILE__OBJ_ID:
                $l_return = '#' . $l_obj_id;
                break;

            case C__VISUALIZATION_PROFILE__OBJ_SYS_ID:
                $l_return = $this->retrieve('SELECT isys_obj__sysid FROM isys_obj WHERE isys_obj__id = ' . $this->convert_sql_id($l_obj_id) . ';')
                    ->get_row_value('isys_obj__sysid');
                break;

            case C__VISUALIZATION_PROFILE__OBJ_TYPE_TITLE:
            case C__VISUALIZATION_PROFILE__OBJ_TYPE_TITLE_ICON:
                $l_return = $l_node_data['data']['obj_type_title'];
                break;

            case C__VISUALIZATION_PROFILE__OBJ_TITLE_CMDB_STATUS:
                $l_sql = 'SELECT isys_obj__title, isys_cmdb_status__color FROM isys_obj
 					LEFT JOIN isys_cmdb_status ON isys_cmdb_status__id = isys_obj__isys_cmdb_status__id
					WHERE isys_obj__id = ' . $this->convert_sql_id($l_obj_id) . ';';

                $l_row = $this->retrieve($l_sql)
                    ->get_row();

                $l_return = [
                    'obj-title'  => $this->language->get($l_row['isys_obj__title']),
                    'cmdb-color' => '#' . $l_row['isys_cmdb_status__color']
                ];
                break;

            case C__VISUALIZATION_PROFILE__OBJ_TITLE_TYPE_TITLE_ICON_CMDB_STATUS:
                $l_sql = 'SELECT isys_cmdb_status__color FROM isys_obj
 					LEFT JOIN isys_cmdb_status ON isys_cmdb_status__id = isys_obj__isys_cmdb_status__id
					WHERE isys_obj__id = ' . $this->convert_sql_id($l_obj_id) . ';';

                $l_row = $this->retrieve($l_sql)
                    ->get_row();

                $l_return = [
                    'obj-title'      => $l_node_data['data']['obj_title'],
                    'obj-type-title' => $l_node_data['data']['obj_type_title'],
                    'cmdb-color'     => '#' . $l_row['isys_cmdb_status__color']
                ];
                break;

            case C__VISUALIZATION_PROFILE__CMDB_STATUS:
                $l_sql = 'SELECT isys_cmdb_status__title, isys_cmdb_status__color FROM isys_obj
 					LEFT JOIN isys_cmdb_status ON isys_cmdb_status__id = isys_obj__isys_cmdb_status__id
					WHERE isys_obj__id = ' . $this->convert_sql_id($l_obj_id) . ';';

                $l_row = $this->retrieve($l_sql)
                    ->get_row();

                $l_return = [
                    'color' => '#' . $l_row['isys_cmdb_status__color'],
                    'title' => $this->language->get($l_row['isys_cmdb_status__title'])
                ];
                break;

            case C__VISUALIZATION_PROFILE__PRIMARY_IP:
                $l_sql = 'SELECT isys_cats_net_ip_addresses_list__title FROM isys_catg_ip_list
					LEFT JOIN isys_cats_net_ip_addresses_list ON isys_cats_net_ip_addresses_list__id = isys_catg_ip_list__isys_cats_net_ip_addresses_list__id
					WHERE isys_catg_ip_list__isys_obj__id =' . $this->convert_sql_id($l_obj_id) . '
					AND isys_catg_ip_list__primary = 1 LIMIT 1;';

                $l_return = $this->retrieve($l_sql)
                    ->get_row_value('isys_cats_net_ip_addresses_list__title') ?: $this->emptyValue;
                break;

            case C__VISUALIZATION_PROFILE__PRIMARY_HOSTNAME:
                $l_sql = 'SELECT isys_catg_ip_list__hostname FROM isys_catg_ip_list
					LEFT JOIN isys_cats_net_ip_addresses_list ON isys_cats_net_ip_addresses_list__id = isys_catg_ip_list__isys_cats_net_ip_addresses_list__id
					WHERE isys_catg_ip_list__isys_obj__id =' . $this->convert_sql_id($l_obj_id) . '
					AND isys_catg_ip_list__primary = 1 LIMIT 1;';

                $l_return = $this->retrieve($l_sql)
                    ->get_row_value('isys_catg_ip_list__hostname') ?: $this->emptyValue;
                break;

            case C__VISUALIZATION_PROFILE__PRIMARY_HOSTNAME_FQDN:
                $l_sql = 'SELECT isys_catg_ip_list__hostname, isys_catg_ip_list__domain FROM isys_catg_ip_list
					WHERE isys_catg_ip_list__isys_obj__id = ' . $this->convert_sql_id($l_obj_id) . '
					AND isys_catg_ip_list__primary = 1
					LIMIT 1;';

                $l_row = $this->retrieve($l_sql)
                    ->get_row();

                if (is_array($l_row) && isset($l_row['isys_catg_ip_list__hostname']) && isset($l_row['isys_catg_ip_list__domain'])) {
                    $l_return = $l_row['isys_catg_ip_list__hostname'] . '.' . $l_row['isys_catg_ip_list__domain'];
                    break;
                }

                $l_return = $this->emptyValue;
                break;

            case C__VISUALIZATION_PROFILE__CATEGORY:
                $l_sql = 'SELECT isys_catg_global_category__title FROM isys_catg_global_list
					LEFT JOIN isys_catg_global_category ON isys_catg_global_category__id = isys_catg_global_list__isys_catg_global_category__id
					WHERE isys_catg_global_list__isys_obj__id = ' . $this->convert_sql_id($l_obj_id) . ' LIMIT 1;';

                $l_return = $this->language->get($this->retrieve($l_sql)
                        ->get_row_value('isys_catg_global_category__title')) ?: $this->emptyValue;
                break;

            case C__VISUALIZATION_PROFILE__PURPOSE:
                $l_sql = 'SELECT isys_purpose__title FROM isys_catg_global_list
					LEFT JOIN isys_purpose ON isys_purpose__id = isys_catg_global_list__isys_purpose__id
					WHERE isys_catg_global_list__isys_obj__id = ' . $this->convert_sql_id($l_obj_id) . ' LIMIT 1;';

                $l_return = $this->language->get($this->retrieve($l_sql)
                        ->get_row_value('isys_purpose__title')) ?: $this->emptyValue;
                break;

            case C__VISUALIZATION_PROFILE__PRIMARY_CONTACT:
                $l_person_row = isys_cmdb_dao_category_g_contact::instance($this->m_db)
                    ->get_contacts_by_obj_id($l_obj_id, true)
                    ->get_row();

                if (is_array($l_person_row)) {
                    $l_return = $l_person_row['isys_cats_person_list__first_name'] . ' ' . $l_person_row['isys_cats_person_list__last_name'] .
                        (!empty($l_person_row['isys_contact_tag__title']) ? ' (' . $l_person_row['isys_contact_tag__title'] . ')' : '');
                    break;
                }

                $l_return = $this->emptyValue;
                break;

            case C__VISUALIZATION_PROFILE__PRIMARY_ACCESS_URL:
                $l_access_row = isys_cmdb_dao_category_g_access::instance($this->m_db)
                    ->get_primary_element($l_obj_id)
                    ->get_row();

                if (is_array($l_access_row)) {
                    if (strpos($l_access_row['isys_catg_access_list__url'], '%') !== false) {
                        $l_return = isys_helper_link::handle_url_variables($l_access_row['isys_catg_access_list__url'], $l_access_row['isys_catg_access_list__isys_obj__id']);
                    } else {
                        $l_return = $l_access_row['isys_catg_access_list__url'];
                    }
                    break;
                }

                $l_return = $this->emptyValue;
                break;

            case C__VISUALIZATION_PROFILE__RELATION_TYPE:
                $l_return = $this->emptyValue;

                if ($l_node_data['data']['relation_obj_id'] > 0) {
                    $l_return = $this->language->get(isys_cmdb_dao_category_s_relation_details::instance($this->m_db)
                            ->get_data(null, $l_node_data['data']['relation_obj_id'])
                            ->get_row_value('isys_relation_type__title'));
                }

                break;
        }

        return $this->contentCache[$key][$p_option] = $l_return;
    }
}
