<?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
 *
 */

/**
 * Class
 *
 * @class CentreonMainCfg
 */
class CentreonMainCfg
{
    // List of broker options Centreon Engine
    // (https://documentation.centreon.com/docs/centreon-engine/en/latest/user/configuration/basics/main_configuration_file_options.html#event-broker-options)
    public const EVENT_BROKER_OPTIONS = [
        -1 => 'All',
        0 => 'None',
        1 => 'Program state',
        2 => 'Timed events',
        4 => 'Service checks',
        8 => 'Host checks',
        16 => 'Event handlers',
        32 => 'Logged data',
        64 => 'Notifications',
        128 => 'Flapping data',
        256 => 'Comment data',
        512 => 'Downtime data',
        1024 => 'System commands',
        2048 => 'OCP data unused',
        4096 => 'Status data',
        8192 => 'Adaptive data',
        16384 => 'External command data',
        32768 => 'Retention data',
        65536 => 'Acknowledgement data',
        131072 => 'Statechange data',
        262144 => 'Reserved18',
        524288 => 'Reserved19',
        1048576 => 'Customvariable data',
        2097152 => 'Group data',
        4194304 => 'Group member data',
        8388608 => 'Module data',
        16777216 => 'Relation data',
        33554432 => 'Command data',
    ];

    /** @var array */
    private $aDefaultBrokerDirective;

    /** @var array */
    private $aInstanceDefaultValues;

    /** @var CentreonDB */
    private $DB;

    /** @var array<string,string> */
    private $loggerDefaultCfg = [
        'log_v2_logger' => 'file',
        'log_level_functions' => 'err',
        'log_level_config' => 'info',
        'log_level_events' => 'info',
        'log_level_checks' => 'info',
        'log_level_notifications' => 'err',
        'log_level_eventbroker' => 'err',
        'log_level_external_command' => 'info',
        'log_level_commands' => 'err',
        'log_level_downtimes' => 'err',
        'log_level_comments' => 'err',
        'log_level_macros' => 'err',
        'log_level_process' => 'info',
        'log_level_runtime' => 'err',
    ];

    /**
     * CentreonMainCfg constructor
     */
    public function __construct()
    {
        $this->DB = new CentreonDB();
        $this->setBrokerOptions();
        $this->setEngineOptions();
    }

    /**
     * Get Default values
     *
     * @return array
     */
    public function getDefaultMainCfg()
    {
        return $this->aInstanceDefaultValues;
    }

    /**
     * Get default engine logger values
     *
     * @return array
     */
    public function getDefaultLoggerCfg(): array
    {
        return $this->loggerDefaultCfg;
    }

    /**
     * Get Default values
     *
     * @return array
     */
    public function getDefaultBrokerOptions()
    {
        return $this->aDefaultBrokerDirective;
    }

    /**
     * Insert the broker modules in cfg_nagios
     *
     * @param int $iId
     * @param ? $source
     *
     * @throws PDOException
     * @return false|void
     */
    public function insertBrokerDefaultDirectives($iId, $source)
    {
        if (empty($iId) || ! in_array($source, ['ui'])) {
            return false;
        }

        $query = "SELECT bk_mod_id FROM `cfg_nagios_broker_module` WHERE cfg_nagios_id = '" . $iId . "'";
        $dbResult = $this->DB->query($query);
        if ($dbResult->rowCount() == 0) {
            $sQuery = "INSERT INTO cfg_nagios_broker_module (`broker_module`, `cfg_nagios_id`) VALUES ('"
                . $this->aDefaultBrokerDirective[$source] . "', " . $iId . ')';
            try {
                $res = $this->DB->query($sQuery);
            } catch (PDOException $e) {
                return false;
            }
        }
    }

    /**
     * @param int $nagiosId
     *
     * @throws PDOException
     */
    public function insertDefaultCfgNagiosLogger(int $nagiosId): void
    {
        $stmt = $this->DB->prepare('INSERT INTO cfg_nagios_logger (`cfg_nagios_id`) VALUES (:nagiosId)');
        $stmt->bindValue('nagiosId', $nagiosId);
        $stmt->execute();
    }

    /**
     * @param int $nagiosId
     * @param int $serverId
     *
     * @throws PDOException
     */
    public function insertCfgNagiosLogger(int $nagiosId, int $serverId): void
    {
        $stmt = $this->DB->prepare(
            'SELECT logger.* FROM cfg_nagios_logger logger, cfg_nagios cfg
            WHERE cfg.nagios_id = logger.cfg_nagios_id AND cfg.nagios_server_id = :serverId'
        );
        $stmt->bindValue('serverId', $serverId, PDO::PARAM_INT);
        $stmt->execute();
        $baseValues = $stmt->fetch();

        if (empty($baseValues)) {
            $baseValues = $this->getDefaultLoggerCfg();
        } else {
            unset($baseValues['id']);
        }
        $baseValues['cfg_nagios_id'] = $nagiosId;
        $columnNames = array_keys($baseValues);

        $stmt = $this->DB->prepare(
            'INSERT INTO cfg_nagios_logger (`' . implode('`, `', $columnNames) . '`)
            VALUES(:' . implode(', :', $columnNames) . ')'
        );
        foreach ($baseValues as $columName => $value) {
            if ($columName === 'cfg_nagios_id') {
                $stmt->bindValue(":{$columName}", $value, PDO::PARAM_INT);
            } else {
                $stmt->bindValue(":{$columName}", $value, PDO::PARAM_STR);
            }
        }
        $stmt->execute();
    }

    /**
     * Insert the instance in cfg_nagios
     *
     * @param int $source The poller id
     * @param int $iId
     * @param string $sName
     *
     * @throws PDOException
     * @return false|mixed
     */
    public function insertServerInCfgNagios($source, $iId, $sName)
    {
        if (empty($sName)) {
            $sName = 'poller';
        }
        if (! isset($this->aInstanceDefaultValues) || ! isset($iId)) {
            return false;
        }

        $res = $this->DB->query('SELECT * FROM cfg_nagios WHERE  nagios_server_id = ' . $source);
        $baseValues = $res->rowCount() == 0 ? $this->aInstanceDefaultValues : $res->fetch();

        $rq = 'INSERT INTO `cfg_nagios` (
            `nagios_name`, `nagios_server_id`, `log_file`, `cfg_dir`,
            `status_file`, `status_update_interval`, `enable_notifications`,
            `execute_service_checks`, `accept_passive_service_checks`, `execute_host_checks`,
            `accept_passive_host_checks`, `enable_event_handlers`, `check_external_commands`,
            `external_command_buffer_slots`, `command_check_interval`, `command_file`,
            `retain_state_information`, `state_retention_file`,`retention_update_interval`,
            `use_retained_program_state`, `use_retained_scheduling_info`, `use_syslog`, `log_notifications`,
            `log_service_retries`, `log_host_retries`, `log_event_handlers`, `log_external_commands`,
            `log_passive_checks`, `sleep_time`, `service_inter_check_delay_method`,
            `host_inter_check_delay_method`, `service_interleave_factor`, `max_concurrent_checks`,
            `max_service_check_spread`, `max_host_check_spread`, `check_result_reaper_frequency`,
            `auto_reschedule_checks`, `enable_flap_detection`, `low_service_flap_threshold`,
            `high_service_flap_threshold`, `low_host_flap_threshold`, `high_host_flap_threshold`,
            `soft_state_dependencies`, `service_check_timeout`, `host_check_timeout`, `event_handler_timeout`,
            `notification_timeout`, `check_for_orphaned_services`, `check_for_orphaned_hosts`,
            `check_service_freshness`, `check_host_freshness`, `date_format`, `illegal_object_name_chars`,
            `illegal_macro_output_chars`, `use_regexp_matching`, `use_true_regexp_matching`, `admin_email`,
            `admin_pager`, `nagios_comment`, `nagios_activate`, `event_broker_options`,
            `enable_predictive_host_dependency_checks`, `enable_predictive_service_dependency_checks`,
            `host_down_disable_service_checks`, `passive_host_checks_are_soft`, `enable_environment_macros`,
            `debug_file`, `debug_level`, `debug_level_opt`, `debug_verbosity`, `max_debug_file_size`, `cfg_file`
            )
            VALUES (
            :nagios_name, :nagios_server_id, :log_file, :cfg_dir,
            :status_file, :status_update_interval, :enable_notifications,
            :execute_service_checks, :accept_passive_service_checks, :execute_host_checks,
            :accept_passive_host_checks, :enable_event_handlers, :check_external_commands,
            :external_command_buffer_slots, :command_check_interval, :command_file,
            :retain_state_information, :state_retention_file,:retention_update_interval,
            :use_retained_program_state, :use_retained_scheduling_info, :use_syslog, :log_notifications,
            :log_service_retries, :log_host_retries, :log_event_handlers, :log_external_commands,
            :log_passive_checks, :sleep_time, :service_inter_check_delay_method,
            :host_inter_check_delay_method, :service_interleave_factor, :max_concurrent_checks,
            :max_service_check_spread, :max_host_check_spread, :check_result_reaper_frequency,
            :auto_reschedule_checks, :enable_flap_detection, :low_service_flap_threshold,
            :high_service_flap_threshold, :low_host_flap_threshold, :high_host_flap_threshold,
            :soft_state_dependencies, :service_check_timeout, :host_check_timeout, :event_handler_timeout,
            :notification_timeout, :check_for_orphaned_services, :check_for_orphaned_hosts,
            :check_service_freshness, :check_host_freshness, :date_format, :illegal_object_name_chars,
            :illegal_macro_output_chars, :use_regexp_matching, :use_true_regexp_matching, :admin_email,
            :admin_pager, :nagios_comment, :nagios_activate, :event_broker_options,
            :enable_predictive_host_dependency_checks, :enable_predictive_service_dependency_checks,
            :host_down_disable_service_checks, :passive_host_checks_are_soft, :enable_environment_macros, :debug_file,
            :debug_level, :debug_level_opt, :debug_verbosity, :max_debug_file_size, :cfg_file
            )';

        $params = [
            ':nagios_name' => 'Centreon Engine ' . $sName,
            ':nagios_server_id' => $iId,
            ':log_file' => $baseValues['log_file'],
            ':cfg_dir' => $baseValues['cfg_dir'],
            ':status_file' => $baseValues['status_file'],
            ':status_update_interval' => $baseValues['status_update_interval'],
            ':enable_notifications' => $baseValues['enable_notifications'],
            ':execute_service_checks' => $baseValues['execute_service_checks'],
            ':accept_passive_service_checks' => $baseValues['accept_passive_service_checks'],
            ':execute_host_checks' => $baseValues['execute_host_checks'],
            ':accept_passive_host_checks' => $baseValues['accept_passive_host_checks'],
            ':enable_event_handlers' => $baseValues['enable_event_handlers'],
            ':check_external_commands' => $baseValues['check_external_commands'],
            ':external_command_buffer_slots' => $baseValues['external_command_buffer_slots'],
            ':command_check_interval' => $baseValues['command_check_interval'],
            ':command_file' => $baseValues['command_file'],
            ':retain_state_information' => $baseValues['retain_state_information'],
            ':state_retention_file' => $baseValues['state_retention_file'],
            ':retention_update_interval' => $baseValues['retention_update_interval'],
            ':use_retained_program_state' => $baseValues['use_retained_program_state'],
            ':use_retained_scheduling_info' => $baseValues['use_retained_scheduling_info'],
            ':use_syslog' => $baseValues['use_syslog'],
            ':log_notifications' => $baseValues['log_notifications'],
            ':log_service_retries' => $baseValues['log_service_retries'],
            ':log_host_retries' => $baseValues['log_host_retries'],
            ':log_event_handlers' => $baseValues['log_event_handlers'],
            ':log_external_commands' => $baseValues['log_external_commands'],
            ':log_passive_checks' => $baseValues['log_passive_checks'],
            ':sleep_time' => $baseValues['sleep_time'],
            ':service_inter_check_delay_method' => $baseValues['service_inter_check_delay_method'],
            ':host_inter_check_delay_method' => $baseValues['host_inter_check_delay_method'],
            ':service_interleave_factor' => $baseValues['service_interleave_factor'],
            ':max_concurrent_checks' => $baseValues['max_concurrent_checks'],
            ':max_service_check_spread' => $baseValues['max_service_check_spread'],
            ':max_host_check_spread' => $baseValues['max_host_check_spread'],
            ':check_result_reaper_frequency' => $baseValues['check_result_reaper_frequency'],
            ':auto_reschedule_checks' => $baseValues['auto_reschedule_checks'],
            ':enable_flap_detection' => $baseValues['enable_flap_detection'],
            ':low_service_flap_threshold' => $baseValues['low_service_flap_threshold'],
            ':high_service_flap_threshold' => $baseValues['high_service_flap_threshold'],
            ':low_host_flap_threshold' => $baseValues['low_host_flap_threshold'],
            ':high_host_flap_threshold' => $baseValues['high_host_flap_threshold'],
            ':soft_state_dependencies' => $baseValues['soft_state_dependencies'],
            ':service_check_timeout' => $baseValues['service_check_timeout'],
            ':host_check_timeout' => $baseValues['host_check_timeout'],
            ':event_handler_timeout' => $baseValues['event_handler_timeout'],
            ':notification_timeout' => $baseValues['notification_timeout'],
            ':check_for_orphaned_services' => $baseValues['check_for_orphaned_services'],
            ':check_for_orphaned_hosts' => $baseValues['check_for_orphaned_hosts'],
            ':check_service_freshness' => $baseValues['check_service_freshness'],
            ':check_host_freshness' => $baseValues['check_host_freshness'],
            ':date_format' => $baseValues['date_format'],
            ':illegal_object_name_chars' => $baseValues['illegal_object_name_chars'],
            ':illegal_macro_output_chars' => $baseValues['illegal_macro_output_chars'],
            ':use_regexp_matching' => $baseValues['use_regexp_matching'],
            ':use_true_regexp_matching' => $baseValues['use_true_regexp_matching'],
            ':admin_email' => $baseValues['admin_email'],
            ':admin_pager' => $baseValues['admin_pager'],
            ':nagios_comment' => $baseValues['nagios_comment'],
            ':nagios_activate' => $baseValues['nagios_activate'],
            ':event_broker_options' => $baseValues['event_broker_options'],
            ':enable_predictive_host_dependency_checks' => $baseValues['enable_predictive_host_dependency_checks'],
            ':enable_predictive_service_dependency_checks' => $baseValues['enable_predictive_service_dependency_checks'],
            ':host_down_disable_service_checks' => $baseValues['host_down_disable_service_checks'],
            ':passive_host_checks_are_soft' => $baseValues['passive_host_checks_are_soft'],
            ':enable_environment_macros' => $baseValues['enable_environment_macros'],
            ':debug_file' => $baseValues['debug_file'],
            ':debug_level' => $baseValues['debug_level'],
            ':debug_level_opt' => $baseValues['debug_level_opt'],
            ':debug_verbosity' => $baseValues['debug_verbosity'],
            ':max_debug_file_size' => $baseValues['max_debug_file_size'],
            ':cfg_file' => $baseValues['cfg_file'],
        ];

        try {
            $stmt = $this->DB->prepare($rq);

            foreach ($params as $paramName => $paramValue) {
                if ($paramName === ':nagios_server_id') {
                    $stmt->bindValue($paramName, $paramValue, PDO::PARAM_INT);
                } else {
                    $stmt->bindValue($paramName, empty($paramValue) ? null : $paramValue, PDO::PARAM_STR);
                }
            }
            $stmt->execute();
        } catch (PDOException $e) {
            return false;
        }

        $res1 = $this->DB->query('SELECT MAX(nagios_id) as last_id FROM `cfg_nagios`');
        $nagios = $res1->fetch();

        return $nagios['last_id'];
    }

    /**
     * Get Broker Module Entries
     *
     * @param int $id
     *
     * @throws PDOException
     * @return array $entries
     */
    public function getBrokerModules($id)
    {
        $dbResult = $this->DB->query('SELECT * FROM cfg_nagios_broker_module WHERE cfg_nagios_id = ' . $id);
        while ($row = $dbResult->fetch()) {
            $entries[] = $row;
        }
        $dbResult->closeCursor();

        return $entries;
    }

    /**
     * Explode the bitwise event broker options to an array for QuickForm
     *
     * @param int $value The value to explode
     *
     * @return array An array of integer
     */
    public function explodeEventBrokerOptions($value)
    {
        return $this->explodeBitwise($value, self::EVENT_BROKER_OPTIONS);
    }

    /**
     * @return void
     */
    private function setBrokerOptions(): void
    {
        $this->aDefaultBrokerDirective = ['ui' => '/usr/lib64/centreon-engine/externalcmd.so'];
    }

    /**
     * @return void
     */
    private function setEngineOptions(): void
    {
        $this->aInstanceDefaultValues = [
            'log_file' => '/var/log/centreon-engine/centengine.log',
            'cfg_dir' => '/etc/centreon-engine/',
            'status_file' => '/var/log/centreon-engine/status.dat',
            'status_update_interval' => '30',
            'enable_notifications' => '1',
            'execute_service_checks' => '1',
            'accept_passive_service_checks' => '1',
            'execute_host_checks' => '1',
            'accept_passive_host_checks' => '1',
            'enable_event_handlers' => '1',
            'check_external_commands' => '1',
            'external_command_buffer_slots' => '4096',
            'command_check_interval' => '1s',
            'command_file' => '/var/lib/centreon-engine/rw/centengine.cmd',
            'retain_state_information' => '1',
            'state_retention_file' => '/var/log/centreon-engine/retention.dat',
            'retention_update_interval' => '60',
            'use_retained_program_state' => '1',
            'use_retained_scheduling_info' => '1',
            'use_syslog' => '0',
            'log_notifications' => '1',
            'log_service_retries' => '1',
            'log_host_retries' => '1',
            'log_event_handlers' => '1',
            'log_external_commands' => '1',
            'log_passive_checks' => '1',
            'sleep_time' => '1',
            'service_inter_check_delay_method' => 's',
            'host_inter_check_delay_method' => 's',
            'service_interleave_factor' => 's',
            'max_concurrent_checks' => '0',
            'max_service_check_spread' => '15',
            'max_host_check_spread' => '15',
            'check_result_reaper_frequency' => '5',
            'auto_reschedule_checks' => '0',
            'enable_flap_detection' => '1',
            'low_service_flap_threshold' => '25.0',
            'high_service_flap_threshold' => '50.0',
            'low_host_flap_threshold' => '25.0',
            'high_host_flap_threshold' => '50.0',
            'soft_state_dependencies' => '0',
            'service_check_timeout' => '60',
            'host_check_timeout' => '12',
            'event_handler_timeout' => '30',
            'notification_timeout' => '30',
            'check_for_orphaned_services' => '0',
            'check_for_orphaned_hosts' => '0',
            'check_service_freshness' => '1',
            'check_host_freshness' => '0',
            'date_format' => 'euro',
            'illegal_object_name_chars' => "~!$%^&*\"|'<>?,()=",
            'illegal_macro_output_chars' => "`~$^&\"|'<>",
            'use_regexp_matching' => '0',
            'use_true_regexp_matching' => '0',
            'admin_email' => 'admin@localhost',
            'admin_pager' => 'admin',
            'nagios_comment' => 'Centreon Engine configuration file',
            'nagios_activate' => '1',
            'event_broker_options' => '-1',
            'nagios_server_id' => '1',
            'enable_predictive_host_dependency_checks' => '1',
            'enable_predictive_service_dependency_checks' => '1',
            'host_down_disable_service_checks' => '1',
            'passive_host_checks_are_soft' => '0',
            'enable_environment_macros' => '0',
            'debug_file' => '/var/log/centreon-engine/centengine.debug',
            'debug_level' => '0',
            'debug_level_opt' => '0',
            'debug_verbosity' => '0',
            'max_debug_file_size' => '1000000000',
            'cfg_file' => 'centengine.cfg',
            'cached_host_check_horizon' => '60',
            'log_pid' => 1,
            'enable_macros_filter' => 0,
            'logger_version' => 'log_v2_enabled',
        ];
    }

    /**
     * Explode the bitwise to an array for QuickForm
     *
     * @param int $value The value to explode
     * @param array $sources The list of bit
     *
     * @return array An array of integer
     */
    private function explodeBitwise($value, $sources)
    {
        if ($value === -1) {
            return [-1 => 1];
        }
        if ($value === 0) {
            return [0 => 1];
        }
        $listOptions = [];
        // Explode all bitwise
        foreach ($sources as $bit => $text) {
            if ($bit !== -1 && $bit !== 0 && ($value & $bit)) {
                $listOptions[$bit] = 1;
            }
        }

        return $listOptions;
    }
}
