<?php

/*
 * Copyright 2005 - 2025 Centreon (https://www.centreon.com/)
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 * For more information : contact@centreon.com
 *
 */

// Require configuration.
require_once realpath(__DIR__ . '/../../../../../../bootstrap.php');
require_once _CENTREON_PATH_ . 'www/class/centreonUtils.class.php';

// Require Specific XML / Ajax Class
require_once _CENTREON_PATH_ . 'www/class/centreonXMLBGRequest.class.php';
require_once _CENTREON_PATH_ . 'www/class/centreonInstance.class.php';
require_once _CENTREON_PATH_ . 'www/class/centreonCriticality.class.php';
require_once _CENTREON_PATH_ . 'www/class/centreonMedia.class.php';

// Require common Files.
require_once _CENTREON_PATH_ . 'www/include/monitoring/status/Common/common-Func.php';
require_once _CENTREON_PATH_ . 'www/include/common/common-Func.php';

// Create XML Request Objects
CentreonSession::start();
$obj = new CentreonXMLBGRequest($dependencyInjector, session_id(), 1, 1, 0, 1);

// Get session
if (isset($_SESSION['centreon'])) {
    $centreon = $_SESSION['centreon'];
} else {
    exit;
}

// Get language
$locale = $centreon->user->get_lang();
putenv("LANG={$locale}");
setlocale(LC_ALL, $locale);
bindtextdomain('messages', _CENTREON_PATH_ . 'www/locale/');
bind_textdomain_codeset('messages', 'UTF-8');
textdomain('messages');

$criticality = new CentreonCriticality($obj->DB);
$instanceObj = new CentreonInstance($obj->DB);
$media = new CentreonMedia($obj->DB);

if (! isset($obj->session_id) || ! CentreonSession::checkSession($obj->session_id, $obj->DB)) {
    echo 'Bad Session ID';

    exit();
}

// Set Default Poller
$obj->getDefaultFilters();

// Check Arguments From GET tab
$o = isset($_GET['o']) ? HtmlAnalyzer::sanitizeAndRemoveTags($_GET['o']) : 'h';
$p = filter_input(INPUT_GET, 'p', FILTER_VALIDATE_INT, ['options' => ['default' => 2]]);
$num = filter_input(INPUT_GET, 'num', FILTER_VALIDATE_INT, ['options' => ['default' => 0]]);
$limit = filter_input(INPUT_GET, 'limit', FILTER_VALIDATE_INT, ['options' => ['default' => 20]]);
$nc = filter_input(INPUT_GET, 'nc', FILTER_VALIDATE_INT, ['options' => ['default' => 0]]);
$criticalityId = filter_input(INPUT_GET, 'criticality', FILTER_VALIDATE_INT, ['options' => ['default' => 0]]);
$serviceToSearch = isset($_GET['search']) ? HtmlAnalyzer::sanitizeAndRemoveTags($_GET['search']) : '';
$hostToSearch = isset($_GET['search_host']) ? HtmlAnalyzer::sanitizeAndRemoveTags($_GET['search_host']) : '';
$outputToSearch = isset($_GET['search_output']) ? HtmlAnalyzer::sanitizeAndRemoveTags($_GET['search_output']) : '';
$sortType = isset($_GET['sort_type']) ? HtmlAnalyzer::sanitizeAndRemoveTags($_GET['sort_type']) : 'host_name';
$order = isset($_GET['order']) && $_GET['order'] === 'DESC' ? 'DESC' : 'ASC';
$statusService = isset($_GET['statusService']) ? HtmlAnalyzer::sanitizeAndRemoveTags($_GET['statusService']) : '';
$statusFilter = isset($_GET['statusFilter']) ? HtmlAnalyzer::sanitizeAndRemoveTags($_GET['statusFilter']) : '';
$dateFormat = 'Y/m/d H:i:s';
// if instance, hostgroup or servicegroup values are not set, displaying each active linked resources
$instance = filter_var($obj->defaultPoller ?? -1, FILTER_VALIDATE_INT);
$hostgroups = filter_var($obj->defaultHostgroups ?? 0, FILTER_VALIDATE_INT);
$servicegroups = filter_var($obj->defaultServicegroups ?? 0, FILTER_VALIDATE_INT);

// Store in session the last type of call
$_SESSION['monitoring_service_status'] = $statusService;
$_SESSION['monitoring_service_status_filter'] = $statusFilter;

// Backup poller selection
$obj->setInstanceHistory($instance);

// Backup criticality id
$obj->setCriticality($criticalityId);

// Saving bound values
$queryValues = [];

// Graphs Tables
$graphs = [];

$tabOrder = [];
$tabOrder['criticality_id'] = ' ORDER BY isnull ' . $order . ', criticality ' . $order . ', h.name, s.description ';
$tabOrder['host_name'] = ' ORDER BY h.name ' . $order . ', s.description ';
$tabOrder['service_description'] = ' ORDER BY s.description ' . $order . ', h.name';
$tabOrder['current_state'] = ' ORDER BY s.state ' . $order . ', h.name, s.description';
$tabOrder['last_state_change'] = ' ORDER BY s.last_state_change ' . $order . ', h.name, s.description';
$tabOrder['last_hard_state_change'] = ' ORDER by s.last_hard_state_change ' . $order . ', h.name, s.description';
$tabOrder['last_check'] = ' ORDER BY s.last_check ' . $order . ', h.name, s.description';
$tabOrder['current_attempt'] = ' ORDER BY s.check_attempt ' . $order . ', h.name, s.description';
$tabOrder['output'] = ' ORDER BY s.output ' . $order . ', h.name, s.description';
$tabOrder['default'] = $tabOrder['criticality_id'];

/**
 * Analyse if services have graphs by performing a single query.
 *
 * @param array $hostServiceIds
 */
function analyseGraphs(array $hostServiceIds): void
{
    if ($hostServiceIds === []) {
        return;
    }
    global $obj, $graphs;
    $request = <<<'SQL'
        SELECT DISTINCT index_data.host_id, index_data.service_id
        FROM index_data
        INNER JOIN metrics
          ON metrics.index_id = index_data.id
          AND index_data.hidden = '0'
        WHERE
        SQL;
    $whereConditions = null;
    $index = 0;
    $valuesToBind = [];
    foreach ($hostServiceIds as $hostServiceId) {
        [$hostId, $serviceId] = explode('_', $hostServiceId);
        if (! empty($whereConditions)) {
            $whereConditions .= ' OR ';
        }
        $whereConditions .= sprintf(' (host_id = :host_id_%d AND service_id = :service_id_%d)', $index, $index);
        $valuesToBind[$index] = ['host_id' => $hostId, 'service_id' => $serviceId];
        $index++;
    }
    $request .= $whereConditions;
    $statement = $obj->DBC->prepare($request);
    foreach ($valuesToBind as $index => $hostServiceId) {
        $statement->bindValue(':host_id_' . $index, $hostServiceId['host_id'], PDO::PARAM_INT);
        $statement->bindValue(':service_id_' . $index, $hostServiceId['service_id'], PDO::PARAM_INT);
    }
    $statement->execute();
    while ($result = $statement->fetch(PDO::FETCH_ASSOC)) {
        $hostServiceId = $result['host_id'] . '_' . $result['service_id'];
        $graphs[$hostServiceId] = true;
    }
}

$request = <<<'SQL_WRAP'
        SELECT SQL_CALC_FOUND_ROWS DISTINCT 1 AS REALTIME, h.name, h.alias, h.address, h.host_id, s.description,
        s.service_id, s.notes, s.notes_url, s.action_url, s.max_check_attempts,
        s.icon_image, s.display_name, s.state, s.output as plugin_output,
        s.state_type, s.check_attempt as current_attempt, s.last_update as status_update_time, s.last_state_change,
        s.last_hard_state_change, s.last_check, s.next_check,
        s.notify, s.acknowledged, s.passive_checks, s.active_checks, s.event_handler_enabled, s.flapping,
        s.scheduled_downtime_depth, s.flap_detection, h.state as host_state, h.acknowledged AS h_acknowledged,
        h.scheduled_downtime_depth AS h_scheduled_downtime_depth,
        h.icon_image AS h_icon_images, h.display_name AS h_display_name, h.action_url AS h_action_url,
        h.notes_url AS h_notes_url, h.notes AS h_notes, h.address,
        h.passive_checks AS h_passive_checks, h.active_checks AS h_active_checks,
        i.name as instance_name, cv.value as criticality, cv.value IS NULL as isnull
        FROM hosts h
        INNER JOIN instances i
          ON h.instance_id = i.instance_id
        INNER JOIN services s
          ON s.host_id = h.host_id
    SQL_WRAP;

if (! $obj->is_admin) {
    $request .= <<<SQL
        
        INNER JOIN centreon_acl
            ON centreon_acl.host_id = h.host_id
            AND centreon_acl.service_id = s.service_id
            AND group_id IN ({$obj->grouplistStr})
        SQL;
}

if (isset($hostgroups) && $hostgroups != 0) {
    $request .= <<<'SQL'
        
        INNER JOIN hosts_hostgroups hg
            ON hg.host_id = h.host_id
            AND hg.hostgroup_id = :hostGroupId
        INNER JOIN hostgroups hg2
            ON hg2.hostgroup_id = hg.hostgroup_id
        SQL;

    $queryValues['hostGroupId'] = [PDO::PARAM_INT => $hostgroups];
}

if (isset($servicegroups) && $servicegroups != 0) {
    $request .= <<<'SQL'
        
        INNER JOIN services_servicegroups ssg
            ON ssg.service_id = s.service_id
            AND ssg.servicegroup_id = :serviceGroupId
        INNER JOIN servicegroups sg
            ON sg.servicegroup_id = ssg.servicegroup_id
        SQL;

    $queryValues['serviceGroupId'] = [PDO::PARAM_INT => $servicegroups];
}

if ($criticalityId) {
    $request .= <<<'SQL'
        
        INNER JOIN customvariables cvs
            ON cvs.service_id = s.service_id
            AND cvs.host_id = h.host_id
            AND cvs.name = 'CRITICALITY_ID'
            AND cvs.value = :criticalityValue
        SQL;

    // the variable bounded to criticalityValue must be an integer. But is inserted in a DB's varchar column
    $queryValues['criticalityValue'] = [PDO::PARAM_STR => $criticalityId];
}

$request .= <<<SQL

    LEFT JOIN customvariables cv
        ON (
            s.service_id = cv.service_id
            AND cv.host_id = s.host_id
            AND cv.name = 'CRITICALITY_LEVEL'
        )
    WHERE s.enabled = 1
    AND h.enabled = 1
    AND h.name NOT LIKE '\_Module\_BAM%'
    SQL;

if ($hostToSearch) {
    $request .= <<<'SQL'
        
        AND (h.name LIKE :hostToSearch
        OR h.alias LIKE :hostToSearch
        OR h.address LIKE :hostToSearch)
        SQL;
    $queryValues['hostToSearch'] = [PDO::PARAM_STR => '%' . $hostToSearch . '%'];
}
if ($serviceToSearch) {
    $request .= ' AND (s.description LIKE :serviceToSearch OR s.display_name LIKE :serviceToSearch) ';
    $queryValues['serviceToSearch'] = [PDO::PARAM_STR => '%' . $serviceToSearch . '%'];
}
if ($outputToSearch) {
    $request .= ' AND s.output LIKE :outputToSearch ';
    $queryValues['outputToSearch'] = [PDO::PARAM_STR => '%' . $outputToSearch . '%'];
}
if (! empty($instance) && $instance != -1) {
    $request .= ' AND h.instance_id = :instanceId';
    $queryValues['instanceId'] = [PDO::PARAM_INT => $instance];
}

if ($statusService == 'svc_unhandled') {
    $request .= <<<'SQL'
        
        AND s.state_type = 1
        AND s.acknowledged = 0
        AND s.scheduled_downtime_depth = 0
        AND h.acknowledged = 0 AND h.scheduled_downtime_depth = 0
        SQL;
}

if ($statusService === 'svc_unhandled' || $statusService === 'svcpb') {
    switch ($statusFilter) {
        case 'warning':
            $request .= ' AND s.state = 1 ';
            break;
        case 'critical':
            $request .= ' AND s.state = 2 ';
            break;
        case 'unknown':
            $request .= ' AND s.state = 3 ';
            break;
        default:
            $request .= ' AND s.state != 0 AND s.state != 4 ';
    }
} elseif ($statusService === 'svc') {
    switch ($statusFilter) {
        case 'ok':
            $request .= ' AND s.state = 0';
            break;
        case 'warning':
            $request .= ' AND s.state = 1 ';
            break;
        case 'critical':
            $request .= ' AND s.state = 2 ';
            break;
        case 'unknown':
            $request .= ' AND s.state = 3 ';
            break;
        case 'pending':
            $request .= ' AND s.state = 4 ';
            break;
    }
}

// Sort order by
$request .= $tabOrder[$sortType] ?? $tabOrder['default'];

$request .= ' LIMIT :numLimit, :limit';
$queryValues['numLimit'] = [PDO::PARAM_INT => ($num * $limit)];
$queryValues['limit'] = [PDO::PARAM_INT => $limit];

// Get Pagination Rows
$sqlError = false;
try {
    $dbResult = $obj->DBC->prepare($request);
    foreach ($queryValues as $bindId => $bindData) {
        foreach ($bindData as $bindType => $bindValue) {
            $dbResult->bindValue($bindId, $bindValue, $bindType);
        }
    }
    $dbResult->execute();

    $numRows = (int) $obj->DBC->query('SELECT FOUND_ROWS() AS REALTIME')->fetchColumn();
} catch (PDOException $e) {
    $sqlError = true;
    $numRows = 0;
}

// Get criticality ids
$critRes = $obj->DBC->query(
    "SELECT value, service_id FROM customvariables WHERE name = 'CRITICALITY_ID' AND service_id IS NOT NULL"
);
$criticalityUsed = 0;
$critCache = [];
if ($critRes->rowCount()) {
    $criticalityUsed = 1;
    while ($critRow = $critRes->fetch()) {
        $critCache[$critRow['service_id']] = $critRow['value'];
    }
}

$isHardStateDurationVisible
    = ! (
        $statusService === 'svc'
        && ($statusFilter === 'ok' || $statusFilter === 'pending')
    );

/**
 * Create Buffer
 */
$obj->XML->startElement('reponse');
$obj->XML->startElement('i');
$obj->XML->writeElement('numrows', $numRows);
$obj->XML->writeElement('num', $num);
$obj->XML->writeElement('limit', $limit);
$obj->XML->writeElement('p', $p);
$obj->XML->writeElement('nc', $nc);
$obj->XML->writeElement('o', $o);
$obj->XML->writeElement('hard_state_label', _('Hard State Duration'));
$obj->XML->writeElement('http_link', _('HTTP Link'));
$obj->XML->writeElement('http_action_link', _('HTTP Action Link'));
$obj->XML->writeElement('host_currently_downtime', _('Host is currently on downtime'));
$obj->XML->writeElement('problem_ack', _('Problem has been acknowledged'));
$obj->XML->writeElement('host_passive_mode', _('This host is only checked in passive mode'));
$obj->XML->writeElement('host_never_checked', _('This host is never checked'));
$obj->XML->writeElement('service_currently_downtime', _('Service is currently on Downtime'));
$obj->XML->writeElement('service_passive_mode', _('This service is only checked in passive mode'));
$obj->XML->writeElement('service_not_active_not_passive', _('This service is neither active nor passive'));
$obj->XML->writeElement('service_flapping', _('This Service is flapping'));
$obj->XML->writeElement('notif_disabled', _('Notification is disabled'));
$obj->XML->writeElement('use_criticality', $criticalityUsed);
$obj->XML->writeElement('use_hard_state_duration', $isHardStateDurationVisible ? 1 : 0);
$obj->XML->endElement();

$host_prev = '';
$ct = 0;
$flag = 0;

if (! $sqlError) {
    $allResults = [];
    $hostServiceIdsToAnalyse = [];
    // We get the host and service IDs to see if they have graphs or not
    while ($result = $dbResult->fetch()) {
        $hostId = (int) $result['host_id'];
        $serviceId = (int) $result['service_id'];
        $graphs[$hostId . '_' . $serviceId] = false;
        $hostServiceIdsToAnalyse[] = $hostId . '_' . $serviceId;
        $allResults[] = $result;
    }

    analyseGraphs($hostServiceIdsToAnalyse);

    foreach ($allResults as $data) {
        $hostId = (int) $data['host_id'];
        $serviceId = (int) $data['service_id'];
        $passive = 0;
        $active = 1;
        $last_check = ' ';
        $duration = ' ';

        // Split the plugin_output
        $outputLines = explode("\n", $data['plugin_output']);
        $pluginShortOuput = $outputLines[0];

        if ($data['last_state_change'] > 0 && time() > $data['last_state_change']) {
            $duration = CentreonDuration::toString(time() - $data['last_state_change']);
        } elseif ($data['last_state_change'] > 0) {
            $duration = ' - ';
        }

        $hard_duration = ' N/S ';
        if (($data['last_hard_state_change'] > 0) && ($data['last_hard_state_change'] >= $data['last_state_change'])) {
            $hard_duration = CentreonDuration::toString(time() - $data['last_hard_state_change']);
        }

        $class = null;
        if ($data['scheduled_downtime_depth'] > 0) {
            $class = 'line_downtime';
        } elseif ($data['state'] == 2) {
            $class = $data['acknowledged'] == 1 ? 'line_ack' : 'list_down';
        } elseif ($data['acknowledged'] == 1) {
            $class = 'line_ack';
        }

        $obj->XML->startElement('l');
        $trClass = $obj->getNextLineClass();
        if (isset($class)) {
            $trClass = $class;
        }
        $obj->XML->writeAttribute('class', $trClass);
        $obj->XML->writeElement('o', $ct++);

        $isMeta = 0;
        $data['host_display_name'] = $data['name'];
        if (! strncmp($data['name'], '_Module_Meta', strlen('_Module_Meta'))) {
            $isMeta = 1;
            $data['host_display_name'] = 'Meta';
            $data['host_state'] = '0';
        }

        if ($host_prev == $data['name']) {
            $obj->XML->writeElement('hc', 'transparent');
            $obj->XML->writeElement('isMeta', $isMeta);
            $obj->XML->writeElement('hdn', $data['host_display_name']);
            $obj->XML->startElement('hn');
            $obj->XML->writeAttribute('none', '1');
            $obj->XML->text(CentreonUtils::escapeSecure(urlencode($data['name'])));
            $obj->XML->endElement();
            $obj->XML->writeElement('hnl', CentreonUtils::escapeSecure(urlencode($data['name'])));
            $obj->XML->writeElement('hid', $data['host_id']);
        } else {
            $host_prev = $data['name'];
            if ($data['h_scheduled_downtime_depth'] == 0) {
                $obj->XML->writeElement('hc', $obj->colorHostInService[$data['host_state']]);
            } else {
                $obj->XML->writeElement('hc', $obj->general_opt['color_downtime']);
            }
            $obj->XML->writeElement('isMeta', $isMeta);
            $obj->XML->writeElement('hnl', CentreonUtils::escapeSecure(urlencode($data['name'])));
            $obj->XML->writeElement('hdn', $data['host_display_name']);
            $obj->XML->startElement('hn');
            $obj->XML->writeAttribute('none', '0');
            $obj->XML->text(CentreonUtils::escapeSecure(urlencode($data['name'])), true, false);
            $obj->XML->endElement();

            $hostNotesUrl = 'none';
            if ($data['h_notes_url']) {
                $hostNotesUrl = str_replace('$HOSTNAME$', $data['name'], $data['h_notes_url']);
                $hostNotesUrl = str_replace('$HOSTALIAS$', $data['alias'], $hostNotesUrl);
                $hostNotesUrl = str_replace('$HOSTADDRESS$', $data['address'], $hostNotesUrl);
                $hostNotesUrl = str_replace('$INSTANCENAME$', $data['instance_name'], $hostNotesUrl);
                $hostNotesUrl = str_replace('$HOSTSTATE$', $obj->statusHost[$data['host_state']], $hostNotesUrl);
                $hostNotesUrl = str_replace('$HOSTSTATEID$', $data['host_state'], $hostNotesUrl);
                $hostNotesUrl = str_replace(
                    '$INSTANCEADDRESS$',
                    $instanceObj->getParam($data['instance_name'], 'ns_ip_address'),
                    $hostNotesUrl
                );
            }
            $obj->XML->writeElement(
                'hnu',
                CentreonUtils::escapeSecure($obj->hostObj->replaceMacroInString($data['name'], $hostNotesUrl))
            );

            $hostActionUrl = 'none';
            if ($data['h_action_url']) {
                $hostActionUrl = str_replace('$HOSTNAME$', $data['name'], $data['h_action_url']);
                $hostActionUrl = str_replace('$HOSTALIAS$', $data['alias'], $hostActionUrl);
                $hostActionUrl = str_replace('$HOSTADDRESS$', $data['address'], $hostActionUrl);
                $hostActionUrl = str_replace('$INSTANCENAME$', $data['instance_name'], $hostActionUrl);
                $hostActionUrl = str_replace('$HOSTSTATE$', $obj->statusHost[$data['host_state']], $hostActionUrl);
                $hostActionUrl = str_replace('$HOSTSTATEID$', $data['host_state'], $hostActionUrl);
                $hostActionUrl = str_replace(
                    '$INSTANCEADDRESS$',
                    $instanceObj->getParam($data['instance_name'], 'ns_ip_address'),
                    $hostActionUrl
                );
            }
            $obj->XML->writeElement(
                'hau',
                CentreonUtils::escapeSecure($obj->hostObj->replaceMacroInString($data['host_id'], $hostActionUrl))
            );

            $obj->XML->writeElement('hnn', CentreonUtils::escapeSecure($data['h_notes']));
            $obj->XML->writeElement('hico', $data['h_icon_images']);
            $obj->XML->writeElement('hip', CentreonUtils::escapeSecure($data['address']));
            $obj->XML->writeElement('hdtm', $data['h_scheduled_downtime_depth']);
            $obj->XML->writeElement(
                'hdtmXml',
                './include/monitoring/downtime/xml/broker/makeXMLForDowntime.php?hid=' . $data['host_id']
            );
            $obj->XML->writeElement('hdtmXsl', './include/monitoring/downtime/xsl/popupForDowntime.xsl');
            $obj->XML->writeElement(
                'hackXml',
                './include/monitoring/acknowlegement/xml/broker/makeXMLForAck.php?hid=' . $data['host_id']
            );
            $obj->XML->writeElement('hackXsl', './include/monitoring/acknowlegement/xsl/popupForAck.xsl');
            $obj->XML->writeElement('hid', $data['host_id']);
        }
        $obj->XML->writeElement('hs', $data['host_state']);

        // Add possibility to use display name
        if ($isMeta) {
            $obj->XML->writeElement('sdn', CentreonUtils::escapeSecure($data['display_name']), false);
        } else {
            $obj->XML->writeElement('sdn', CentreonUtils::escapeSecure($data['description']), false);
        }
        $obj->XML->writeElement('sd', CentreonUtils::escapeSecure($data['description']), false);

        $obj->XML->writeElement('sico', $data['icon_image']);
        $obj->XML->writeElement('sdl', CentreonUtils::escapeSecure(urlencode($data['description'])));
        $obj->XML->writeElement('svc_id', $data['service_id']);
        $obj->XML->writeElement('sc', $obj->colorService[$data['state']]);
        $obj->XML->writeElement('cs', _($obj->statusService[$data['state']]), false);
        $obj->XML->writeElement('ssc', $data['state']);
        $obj->XML->writeElement('po', CentreonUtils::escapeSecure($pluginShortOuput));
        $obj->XML->writeElement(
            'ca',
            $data['current_attempt'] . '/' . $data['max_check_attempts']
            . ' (' . $obj->stateType[$data['state_type']] . ')'
        );
        if (isset($data['criticality']) && $data['criticality'] != '' && isset($critCache[$data['service_id']])) {
            $obj->XML->writeElement('hci', 1); // has criticality
            $critData = $criticality->getData($critCache[$data['service_id']], true);
            $obj->XML->writeElement('ci', $media->getFilename($critData['icon_id']));
            $obj->XML->writeElement('cih', CentreonUtils::escapeSecure($critData['name']));
        } else {
            $obj->XML->writeElement('hci', 0); // has no criticality
        }
        $obj->XML->writeElement('ne', $data['notify']);
        $obj->XML->writeElement('pa', $data['acknowledged']);
        $obj->XML->writeElement('pc', $data['passive_checks']);
        $obj->XML->writeElement('ac', $data['active_checks']);
        $obj->XML->writeElement('eh', $data['event_handler_enabled']);
        $obj->XML->writeElement('is', $data['flapping']);
        $obj->XML->writeElement('dtm', $data['scheduled_downtime_depth']);
        $obj->XML->writeElement(
            'dtmXml',
            './include/monitoring/downtime/xml/broker/makeXMLForDowntime.php?hid='
            . $data['host_id'] . '&svc_id=' . $data['service_id']
        );
        $obj->XML->writeElement('dtmXsl', './include/monitoring/downtime/xsl/popupForDowntime.xsl');
        $obj->XML->writeElement(
            'ackXml',
            './include/monitoring/acknowlegement/xml/broker/makeXMLForAck.php?hid='
            . $data['host_id'] . '&svc_id=' . $data['service_id']
        );
        $obj->XML->writeElement('ackXsl', './include/monitoring/acknowlegement/xsl/popupForAck.xsl');

        if ($data['notes'] != '') {
            $data['notes'] = str_replace('$SERVICEDESC$', $data['description'], $data['notes']);
            $data['notes'] = str_replace('$HOSTNAME$', $data['name'], $data['notes']);
            if (isset($data['alias']) && $data['alias']) {
                $data['notes'] = str_replace('$HOSTALIAS$', $data['alias'], $data['notes']);
            }
            if (isset($data['address']) && $data['address']) {
                $data['notes'] = str_replace('$HOSTADDRESS$', $data['address'], $data['notes']);
            }
            if (isset($data['instance_name']) && $data['instance_name']) {
                $data['notes'] = str_replace('$INSTANCENAME$', $data['instance_name'], $data['notes']);
                $data['notes'] = str_replace(
                    '$INSTANCEADDRESS$',
                    $instanceObj->getParam($data['instance_name'], 'ns_ip_address'),
                    $data['notes']
                );
            }
            $obj->XML->writeElement('snn', CentreonUtils::escapeSecure($data['notes']));
        } else {
            $obj->XML->writeElement('snn', 'none');
        }

        if ($data['notes_url'] != '') {
            $data['notes_url'] = str_replace('$SERVICEDESC$', $data['description'], $data['notes_url']);
            $data['notes_url'] = str_replace('$SERVICESTATEID$', $data['state'], $data['notes_url']);
            $data['notes_url'] = str_replace(
                '$SERVICESTATE$',
                $obj->statusService[$data['state']],
                $data['notes_url']
            );
            $data['notes_url'] = str_replace('$HOSTNAME$', $data['name'], $data['notes_url']);
            if (isset($data['alias']) && $data['alias']) {
                $data['notes_url'] = str_replace('$HOSTALIAS$', $data['alias'], $data['notes_url']);
            }
            if (isset($data['address']) && $data['address']) {
                $data['notes_url'] = str_replace('$HOSTADDRESS$', $data['address'], $data['notes_url']);
            }
            if (isset($data['instance_name']) && $data['instance_name']) {
                $data['notes_url'] = str_replace('$INSTANCENAME$', $data['instance_name'], $data['notes_url']);
                $data['notes_url'] = str_replace(
                    '$INSTANCEADDRESS$',
                    $instanceObj->getParam($data['instance_name'], 'ns_ip_address'),
                    $data['notes_url']
                );
            }
            $obj->XML->writeElement(
                'snu',
                CentreonUtils::escapeSecure(
                    $obj->serviceObj->replaceMacroInString($data['service_id'], $data['notes_url'])
                )
            );
        } else {
            $obj->XML->writeElement('snu', 'none');
        }

        if ($data['action_url'] != '') {
            $data['action_url'] = str_replace('$SERVICEDESC$', $data['description'], $data['action_url']);
            $data['action_url'] = str_replace('$SERVICESTATEID$', $data['state'], $data['action_url']);
            $data['action_url'] = str_replace(
                '$SERVICESTATE$',
                $obj->statusService[$data['state']],
                $data['action_url']
            );
            $data['action_url'] = str_replace('$HOSTNAME$', $data['name'], $data['action_url']);
            if (isset($data['alias']) && $data['alias']) {
                $data['action_url'] = str_replace('$HOSTALIAS$', $data['alias'], $data['action_url']);
            }
            if (isset($data['address']) && $data['address']) {
                $data['action_url'] = str_replace('$HOSTADDRESS$', $data['address'], $data['action_url']);
            }
            if (isset($data['instance_name']) && $data['instance_name']) {
                $data['action_url'] = str_replace('$INSTANCENAME$', $data['instance_name'], $data['action_url']);
                $data['action_url'] = str_replace(
                    '$INSTANCEADDRESS$',
                    $instanceObj->getParam($data['instance_name'], 'ns_ip_address'),
                    $data['action_url']
                );
            }
            $obj->XML->writeElement(
                'sau',
                CentreonUtils::escapeSecure(
                    $obj->serviceObj->replaceMacroInString($data['service_id'], $data['action_url'])
                )
            );
        } else {
            $obj->XML->writeElement('sau', 'none');
        }

        if ($data['notes'] != '') {
            $data['notes'] = str_replace('$SERVICEDESC$', $data['description'], $data['notes']);
            $data['notes'] = str_replace('$HOSTNAME$', $data['name'], $data['notes']);
            if (isset($data['alias']) && $data['alias']) {
                $data['notes'] = str_replace('$HOSTALIAS$', $data['alias'], $data['notes']);
            }
            if (isset($data['address']) && $data['address']) {
                $data['notes'] = str_replace('$HOSTADDRESS$', $data['address'], $data['notes']);
            }
            $obj->XML->writeElement('sn', CentreonUtils::escapeSecure($data['notes']));
        } else {
            $obj->XML->writeElement('sn', 'none');
        }

        $obj->XML->writeElement('fd', $data['flap_detection']);
        $obj->XML->writeElement('ha', $data['h_acknowledged']);
        $obj->XML->writeElement('hae', $data['h_active_checks']);
        $obj->XML->writeElement('hpe', $data['h_passive_checks']);
        $obj->XML->writeElement('nc', $obj->GMT->getDate($dateFormat, $data['next_check']));
        if ($data['last_check'] != 0) {
            $obj->XML->writeElement('lc', CentreonDuration::toString(time() - $data['last_check']));
        } else {
            $obj->XML->writeElement('lc', 'N/A');
        }
        $obj->XML->writeElement('d', $duration);
        $obj->XML->writeElement('rd', (time() - $data['last_state_change']));
        $obj->XML->writeElement('last_hard_state_change', $hard_duration);

        // Get Service Graph index
        $obj->XML->writeElement('hasGraph', $graphs[$hostId . '_' . $serviceId] ? '1' : '0');
        $obj->XML->writeElement('chartIcon', returnSvg('www/img/icons/chart.svg', 'var(--icons-fill-color)', 18, 18));
        $obj->XML->endElement();
    }
    $dbResult->closeCursor();
}

unset($data, $host_status);

if (! $ct) {
    $obj->XML->writeElement('infos', 'none');
}

$obj->XML->writeElement('sid', $obj->session_id);
$obj->XML->endElement();

// Send Header
$obj->header();

// Send XML
$obj->XML->output();
