<?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 CentreonTraps
 */
class CentreonTraps
{
    /** @var CentreonDB */
    protected $db;

    /** @var HTML_QuickFormCustom */
    protected $form;

    /** @var Centreon */
    protected $centreon;

    /**
     * CentreonTraps constructor
     *
     * @param CentreonDB $db
     * @param Centreon $centreon
     * @param HTML_QuickFormCustom $form
     *
     * @throws Exception
     */
    public function __construct($db, $centreon = null, $form = null)
    {
        if (! isset($db)) {
            throw new Exception('Db connector object is required');
        }
        $this->db = $db;
        $this->centreon = $centreon;
        $this->form = $form;
    }

    /**
     * Sets form if not passed to constructor beforehands
     *
     * @param $form
     */
    public function setForm($form): void
    {
        $this->form = $form;
    }

    /**
     * Check if the OID has the good Format
     *
     * @param null|string $oid
     * @return bool
     */
    public function testOidFormat($oid = null)
    {
        return (bool) (preg_match('/^(\.([0-2]))|([0-2])((\.0)|(\.([1-9][0-9]*)))*$/', $oid) == true);
    }

    /**
     * Delete Traps
     *
     * @param array $traps
     *
     * @throws PDOException
     */
    public function delete($traps = []): void
    {
        $querySelect = 'SELECT traps_name FROM `traps` WHERE `traps_id` = :trapsId LIMIT 1';
        $queryDelete = 'DELETE FROM traps WHERE traps_id = :trapsId ';

        $statementSelect = $this->db->prepare($querySelect);
        $statementDelete = $this->db->prepare($queryDelete);
        foreach (array_keys($traps) as $trapsId) {
            if (is_int($trapsId)) {
                $statementSelect->bindValue(':trapsId', $trapsId, PDO::PARAM_INT);
                $statementSelect->execute();
                $row = $statementSelect->fetch(PDO::FETCH_ASSOC);

                $statementDelete->bindValue(':trapsId', $trapsId, PDO::PARAM_INT);
                $statementDelete->execute();
                if ($statementDelete->rowCount() > 0) {
                    $this->centreon->CentreonLogAction->insertLog('traps', $trapsId, $row['traps_name'], 'd');
                }
            }
        }
    }

    /**
     * Indicates if the trap name already exists
     *
     * @param string $trapName Trap name to find
     *
     * @throws PDOException
     * @return bool
     */
    public function trapNameExists(string $trapName)
    {
        if (! empty($trapName)) {
            $statement = $this->db->prepare(
                'SELECT COUNT(*) AS total FROM traps WHERE traps_name = :trap_name'
            );
            $statement->bindValue(':trap_name', $trapName, PDO::PARAM_STR);
            $statement->execute();
            $result = $statement->fetch(PDO::FETCH_ASSOC);

            return ((int) $result['total']) > 0;
        }

        return false;
    }

    /**
     * duplicate traps
     *
     * @param array $traps
     * @param array $nbrDup
     *
     * @throws PDOException
     */
    public function duplicate($traps = [], $nbrDup = []): void
    {
        $querySelectTrap = 'SELECT * FROM traps WHERE traps_id = :trapsId LIMIT 1';
        $queryInsertTrapServiceRelation = '
            INSERT INTO traps_service_relation (traps_id, service_id)
            (SELECT :maxTrapsId, service_id
                FROM traps_service_relation
                WHERE traps_id = :trapsId)';
        $queryInsertPreexec = '
            INSERT INTO traps_preexec (trap_id, tpe_string, tpe_order)
            (SELECT :maxTrapsId, tpe_string, tpe_order
                FROM traps_preexec
                WHERE trap_id = :trapsId)';
        $querySelectMatching = 'SELECT * FROM traps_matching_properties WHERE trap_id = :trapsId';
        $queryInsertMatching = '
            INSERT INTO traps_matching_properties
            (`trap_id`,`tmo_order`,`tmo_regexp`,`tmo_string`,`tmo_status`,`severity_id`)
            VALUES (:trap_id, :tmo_order, :tmo_regexp, :tmo_string, :tmo_status, :severity_id)';

        $stmtSelectTrap = $this->db->prepare($querySelectTrap);
        $stmtInsertTrapServiceRelation = $this->db->prepare($queryInsertTrapServiceRelation);
        $stmtInsertPreexec = $this->db->prepare($queryInsertPreexec);
        $stmtSelectMatching = $this->db->prepare($querySelectMatching);
        $stmtInsertMatching = $this->db->prepare($queryInsertMatching);
        foreach (array_keys($traps) as $trapsId) {
            if (is_int($trapsId)) {

                $stmtSelectTrap->bindValue(':trapsId', $trapsId, PDO::PARAM_INT);
                $stmtSelectTrap->execute();

                $trapConfigurations = $stmtSelectTrap->fetch(PDO::FETCH_ASSOC);
                $trapConfigurations['traps_id'] = '';
                for ($newIndex = 1; $newIndex <= $nbrDup[$trapsId]; $newIndex++) {
                    $val = null;
                    $trapName = null;
                    $fields = [];
                    foreach ($trapConfigurations as $cfgName => $cfgValue) {
                        if ($cfgName == 'traps_name') {
                            $cfgValue .= '_' . $newIndex;
                            $trapName = $cfgValue;
                            $fields['traps_name'] = $trapName;
                        } elseif ($cfgName != 'traps_id') {
                            $fields[$cfgName] = $cfgValue;
                        }

                        if (is_null($val)) {
                            $val .= ($cfgValue == null)
                                ? 'NULL'
                                : "'" . $this->db->escape($cfgValue) . "'";
                        } else {
                            $val .= ($cfgValue == null)
                                ? ', NULL'
                                : ", '" . $this->db->escape($cfgValue) . "'";
                        }
                    }

                    if (! is_null($val)
                        && ! empty($trapName)
                        && ! $this->trapNameExists($trapName)
                    ) {
                        $this->db->query("INSERT INTO traps VALUES ({$val})");
                        $res2 = $this->db->query('SELECT MAX(traps_id) FROM traps');
                        $maxId = $res2->fetch();

                        $stmtInsertTrapServiceRelation->bindValue(
                            ':maxTrapsId',
                            $maxId['MAX(traps_id)'],
                            PDO::PARAM_INT
                        );
                        $stmtInsertTrapServiceRelation->bindValue(':trapsId', $trapsId, PDO::PARAM_INT);
                        $stmtInsertTrapServiceRelation->execute();

                        $stmtInsertPreexec->bindValue(':maxTrapsId', $maxId['MAX(traps_id)'], PDO::PARAM_INT);
                        $stmtInsertPreexec->bindValue(':trapsId', $trapsId, PDO::PARAM_INT);
                        $stmtInsertPreexec->execute();

                        $stmtSelectMatching->bindValue(':trapsId', $trapsId, PDO::PARAM_INT);
                        $stmtSelectMatching->execute();

                        while ($row = $stmtSelectMatching->fetch()) {
                            $severity = $row['severity_id'] ?? null;

                            $stmtInsertMatching->bindValue(':trap_id', $maxId['MAX(traps_id)'], PDO::PARAM_INT);
                            $stmtInsertMatching->bindValue(':tmo_order', $row['tmo_order'], PDO::PARAM_INT);
                            $stmtInsertMatching->bindValue(':tmo_regexp', $row['tmo_regexp'], PDO::PARAM_STR);
                            $stmtInsertMatching->bindValue(':tmo_string', $row['tmo_string'], PDO::PARAM_STR);
                            $stmtInsertMatching->bindValue(':tmo_status', $row['tmo_status'], PDO::PARAM_INT);
                            $stmtInsertMatching->bindValue(':severity_id', $severity, PDO::PARAM_INT);
                            $stmtInsertMatching->execute();
                        }

                        $this->centreon->CentreonLogAction->insertLog(
                            'traps',
                            $maxId['MAX(traps_id)'],
                            $trapName,
                            'a',
                            $fields
                        );
                    }
                }
            }
        }
    }

    /**
     * @param int|null $traps_id
     *
     * @throws InvalidArgumentException
     * @throws PDOException
     * @return null|void
     */
    public function update($traps_id = null)
    {
        if (! $traps_id) {
            return null;
        }

        $ret = $this->form->getSubmitValues();
        $retValue = [];

        $rq = 'UPDATE traps SET ';
        $rq .= '`traps_name` = ';
        if (isset($ret['traps_name']) && $ret['traps_name'] != null) {
            $rq .= ':traps_name, ';
            $retValue[':traps_name'] = $ret['traps_name'];
        } else {
            $rq .= 'NULL, ';
        }

        $rq .= '`traps_oid` = ';
        if (isset($ret['traps_oid']) && $ret['traps_oid'] != null) {
            $rq .= ':traps_oid, ';
            $retValue[':traps_oid'] = $ret['traps_oid'];
        } else {
            $rq .= 'NULL, ';
        }

        $rq .= '`traps_args` = ';
        if (isset($ret['traps_args']) && $ret['traps_args'] != null) {
            $rq .= ':traps_args, ';
            $retValue[':traps_args'] = $ret['traps_args'];
        } else {
            $rq .= 'NULL, ';
        }

        $rq .= '`traps_status` = ';
        if (isset($ret['traps_status']) && $ret['traps_status'] != null) {
            $rq .= ':traps_status, ';
            $retValue[':traps_status'] = $ret['traps_status'];
        } else {
            $rq .= 'NULL, ';
        }

        $rq .= '`severity_id` = ';
        if (isset($ret['severity']) && $ret['severity'] != null) {
            $rq .= ':severity, ';
            $retValue[':severity'] = $ret['severity'];
        } else {
            $rq .= 'NULL, ';
        }

        $rq .= '`traps_submit_result_enable` = ';
        if (isset($ret['traps_submit_result_enable']) && $ret['traps_submit_result_enable'] != null) {
            $rq .= ':traps_submit_result_enable, ';
            $retValue[':traps_submit_result_enable'] = $ret['traps_submit_result_enable'];
        } else {
            $rq .= "'0', ";
        }

        $rq .= '`traps_reschedule_svc_enable` = ';
        if (isset($ret['traps_reschedule_svc_enable']) && $ret['traps_reschedule_svc_enable'] != null) {
            $rq .= ':traps_reschedule_svc_enable, ';
            $retValue[':traps_reschedule_svc_enable'] = $ret['traps_reschedule_svc_enable'];
        } else {
            $rq .= "'0', ";
        }

        $rq .= '`traps_execution_command` = ';
        if (isset($ret['traps_execution_command']) && $ret['traps_execution_command'] != null) {
            $rq .= ':traps_execution_command, ';
            $retValue[':traps_execution_command'] = $ret['traps_execution_command'];
        } else {
            $rq .= 'NULL, ';
        }

        $rq .= '`traps_execution_command_enable` = ';
        if (isset($ret['traps_execution_command_enable']) && $ret['traps_execution_command_enable'] != null) {
            $rq .= ':traps_execution_command_enable, ';
            $retValue[':traps_execution_command_enable'] = $ret['traps_execution_command_enable'];
        } else {
            $rq .= "'0', ";
        }

        $rq .= '`traps_advanced_treatment` = ';
        if (isset($ret['traps_advanced_treatment']) && $ret['traps_advanced_treatment'] != null) {
            $rq .= ':traps_advanced_treatment, ';
            $retValue[':traps_advanced_treatment'] = $ret['traps_advanced_treatment'];
        } else {
            $rq .= "'0', ";
        }

        $rq .= '`traps_comments` = ';
        if (isset($ret['traps_comments']) && $ret['traps_comments'] != null) {
            $rq .= ':traps_comments, ';
            $retValue[':traps_comments'] = $ret['traps_comments'];
        } else {
            $rq .= 'NULL, ';
        }

        $rq .= '`traps_routing_mode` = ';
        if (isset($ret['traps_routing_mode']) && $ret['traps_routing_mode'] != null) {
            $rq .= ':traps_routing_mode, ';
            $retValue[':traps_routing_mode'] = $ret['traps_routing_mode'];
        } else {
            $rq .= "'0', ";
        }

        $rq .= '`traps_routing_value` = ';
        if (isset($ret['traps_routing_value']) && $ret['traps_routing_value'] != null) {
            $rq .= ':traps_routing_value, ';
            $retValue[':traps_routing_value'] = $ret['traps_routing_value'];
        } else {
            $rq .= 'NULL, ';
        }

        $rq .= '`traps_routing_filter_services` = ';
        if (isset($ret['traps_routing_filter_services']) && $ret['traps_routing_filter_services'] != null) {
            $rq .= ':traps_routing_filter_services, ';
            $retValue[':traps_routing_filter_services'] = $ret['traps_routing_filter_services'];
        } else {
            $rq .= 'NULL, ';
        }

        $rq .= '`manufacturer_id` = ';
        if (isset($ret['manufacturer_id']) && $ret['manufacturer_id'] != null) {
            $rq .= ':manufacturer_id, ';
            $retValue[':manufacturer_id'] = $ret['manufacturer_id'];
        } else {
            $rq .= 'NULL, ';
        }

        $rq .= '`traps_log` = ';
        if (isset($ret['traps_log']) && $ret['traps_log'] != null) {
            $rq .= ':traps_log, ';
            $retValue[':traps_log'] = $ret['traps_log'];
        } else {
            $rq .= "'0', ";
        }

        $rq .= '`traps_exec_interval` = ';
        if (isset($ret['traps_exec_interval']) && $ret['traps_exec_interval'] != null) {
            $rq .= ':traps_exec_interval, ';
            $retValue[':traps_exec_interval'] = $ret['traps_exec_interval'];
        } else {
            $rq .= 'NULL, ';
        }

        $rq .= '`traps_exec_interval_type` = ';
        if (isset($ret['traps_exec_interval_type']['traps_exec_interval_type'])
            && $ret['traps_exec_interval_type']['traps_exec_interval_type'] != null) {
            $rq .= ':traps_exec_interval_type, ';
            $retValue[':traps_exec_interval_type'] = $ret['traps_exec_interval_type']['traps_exec_interval_type'];
        } else {
            $rq .= "'0', ";
        }

        $rq .= '`traps_exec_method` = ';
        if (isset($ret['traps_exec_method']['traps_exec_method'])
            && $ret['traps_exec_method']['traps_exec_method'] != null) {
            $rq .= ':traps_exec_method, ';
            $retValue[':traps_exec_method'] = $ret['traps_exec_method']['traps_exec_method'];
        } else {
            $rq .= "'0', ";
        }

        $rq .= '`traps_downtime` = ';
        if (isset($ret['traps_downtime']['traps_downtime'])
            && $ret['traps_downtime']['traps_downtime'] != null) {
            $rq .= ':traps_downtime, ';
            $retValue[':traps_downtime'] = $ret['traps_downtime']['traps_downtime'];
        } else {
            $rq .= "'0', ";
        }

        $rq .= '`traps_output_transform` = ';
        if (isset($ret['traps_output_transform']) && $ret['traps_output_transform'] != null) {
            $rq .= ':traps_output_transform, ';
            $retValue[':traps_output_transform'] = $ret['traps_output_transform'];
        } else {
            $rq .= 'NULL, ';
        }

        $rq .= '`traps_advanced_treatment_default` = ';
        if (isset($ret['traps_advanced_treatment_default']) && $ret['traps_advanced_treatment_default'] != null) {
            $rq .= ':traps_advanced_treatment_default, ';
            $retValue[':traps_advanced_treatment_default'] = $ret['traps_advanced_treatment_default'];
        } else {
            $rq .= "'0', ";
        }

        $rq .= '`traps_timeout` = ';
        if (isset($ret['traps_timeout']) && $ret['traps_timeout'] != null) {
            $rq .= ':traps_timeout, ';
            $retValue[':traps_timeout'] = $ret['traps_timeout'];
        } else {
            $rq .= 'NULL, ';
        }

        $rq .= '`traps_customcode` = ';
        if (isset($ret['traps_customcode']) && $ret['traps_customcode'] != null) {
            $rq .= ':traps_customcode, ';
            $retValue[':traps_customcode'] = $ret['traps_customcode'];
        } else {
            $rq .= 'NULL, ';
        }

        $rq .= '`traps_mode` = ';
        if (isset($ret['traps_mode']['traps_mode']) && $ret['traps_mode']['traps_mode'] != null) {
            $rq .= ':traps_mode ';
            $retValue[':traps_mode'] = $ret['traps_mode']['traps_mode'];
        } else {
            $rq .= 'NULL ';
        }

        $rq .= 'WHERE `traps_id` = :traps_id ';
        $retValue[':traps_id'] = (int) $traps_id;

        $stmt = $this->db->prepare($rq);
        foreach ($retValue as $key => $value) {
            $stmt->bindValue($key, $value);
        }
        $stmt->execute();
        $this->setMatchingOptions($traps_id);
        $this->setServiceRelations($traps_id);
        $this->setServiceTemplateRelations($traps_id);
        $this->setPreexec($traps_id);

        // Prepare value for changelog
        $fields = CentreonLogAction::prepareChanges($ret);
        $this->centreon->CentreonLogAction->insertLog('traps', $traps_id, $fields['traps_name'], 'c', $fields);
    }

    /**
     * Insert Traps
     *
     * @param array $ret
     *
     * @throws InvalidArgumentException
     * @throws PDOException
     * @return mixed
     */
    public function insert($ret = [])
    {
        if (! count($ret)) {
            $ret = $this->form->getSubmitValues();
        }

        $sqlValue = '';
        $retValue = [];

        $rq = 'INSERT INTO traps (';
        $rq .= '`traps_name`, ';
        if (isset($ret['traps_name']) && $ret['traps_name'] != null) {
            $sqlValue .= ':traps_name, ';
            $retValue[':traps_name'] = $ret['traps_name'];
        } else {
            $sqlValue .= 'NULL, ';
        }

        $rq .= '`traps_oid`, ';
        if (isset($ret['traps_oid']) && $ret['traps_oid'] != null) {
            $sqlValue .= ':traps_oid, ';
            $retValue[':traps_oid'] = $ret['traps_oid'];
        } else {
            $sqlValue .= 'NULL, ';
        }

        $rq .= '`traps_args`, ';
        if (isset($ret['traps_args']) && $ret['traps_args'] != null) {
            $sqlValue .= ':traps_args, ';
            $retValue[':traps_args'] = $ret['traps_args'];
        } else {
            $sqlValue .= 'NULL, ';
        }

        $rq .= '`traps_status`, ';
        if (isset($ret['traps_status']) && $ret['traps_status'] != null) {
            $sqlValue .= ':traps_status, ';
            $retValue[':traps_status'] = $ret['traps_status'];
        } else {
            $sqlValue .= 'NULL, ';
        }

        $rq .= '`severity_id`, ';
        if (isset($ret['severity']) && $ret['severity'] != null) {
            $sqlValue .= ':severity, ';
            $retValue[':severity'] = $ret['severity'];
        } else {
            $sqlValue .= 'NULL, ';
        }

        $rq .= '`traps_submit_result_enable`, ';
        if (isset($ret['traps_submit_result_enable']) && $ret['traps_submit_result_enable'] != null) {
            $sqlValue .= ':traps_submit_result_enable, ';
            $retValue[':traps_submit_result_enable'] = $ret['traps_submit_result_enable'];
        } else {
            $sqlValue .= "'0', ";
        }

        $rq .= '`traps_reschedule_svc_enable`, ';
        if (isset($ret['traps_reschedule_svc_enable']) && $ret['traps_reschedule_svc_enable'] != null) {
            $sqlValue .= ':traps_reschedule_svc_enable, ';
            $retValue[':traps_reschedule_svc_enable'] = $ret['traps_reschedule_svc_enable'];
        } else {
            $sqlValue .= "'0', ";
        }

        $rq .= '`traps_execution_command`, ';
        if (isset($ret['traps_execution_command']) && $ret['traps_execution_command'] != null) {
            $sqlValue .= ':traps_execution_command, ';
            $retValue[':traps_execution_command'] = $ret['traps_execution_command'];
        } else {
            $sqlValue .= 'NULL, ';
        }

        $rq .= '`traps_execution_command_enable`, ';
        if (isset($ret['traps_execution_command_enable']) && $ret['traps_execution_command_enable'] != null) {
            $sqlValue .= ':traps_execution_command_enable, ';
            $retValue[':traps_execution_command_enable'] = $ret['traps_execution_command_enable'];
        } else {
            $sqlValue .= "'0', ";
        }

        $rq .= '`traps_advanced_treatment`, ';
        if (isset($ret['traps_advanced_treatment']) && $ret['traps_advanced_treatment'] != null) {
            $sqlValue .= ':traps_advanced_treatment, ';
            $retValue[':traps_advanced_treatment'] = $ret['traps_advanced_treatment'];
        } else {
            $sqlValue .= "'0', ";
        }

        $rq .= '`traps_comments`, ';
        if (isset($ret['traps_comments']) && $ret['traps_comments'] != null) {
            $sqlValue .= ':traps_comments, ';
            $retValue[':traps_comments'] = $ret['traps_comments'];
        } else {
            $sqlValue .= 'NULL, ';
        }

        $rq .= '`traps_routing_mode`, ';
        if (isset($ret['traps_routing_mode']) && $ret['traps_routing_mode'] != null) {
            $sqlValue .= ':traps_routing_mode, ';
            $retValue[':traps_routing_mode'] = $ret['traps_routing_mode'];
        } else {
            $sqlValue .= "'0', ";
        }

        $rq .= '`traps_routing_value`, ';
        if (isset($ret['traps_routing_value']) && $ret['traps_routing_value'] != null) {
            $sqlValue .= ':traps_routing_value, ';
            $retValue[':traps_routing_value'] = $ret['traps_routing_value'];
        } else {
            $sqlValue .= 'NULL, ';
        }

        $rq .= '`traps_routing_filter_services`, ';
        if (isset($ret['traps_routing_filter_services']) && $ret['traps_routing_filter_services'] != null) {
            $sqlValue .= ':traps_routing_filter_services, ';
            $retValue[':traps_routing_filter_services'] = $ret['traps_routing_filter_services'];
        } else {
            $sqlValue .= 'NULL, ';
        }

        $rq .= '`manufacturer_id`, ';
        if (isset($ret['manufacturer_id']) && $ret['manufacturer_id'] != null) {
            $sqlValue .= ':manufacturer_id, ';
            $retValue[':manufacturer_id'] = $ret['manufacturer_id'];
        } else {
            $sqlValue .= 'NULL, ';
        }

        $rq .= '`traps_log`, ';
        if (isset($ret['traps_log']) && $ret['traps_log'] != null) {
            $sqlValue .= ':traps_log, ';
            $retValue[':traps_log'] = $ret['traps_log'];
        } else {
            $sqlValue .= "'0', ";
        }

        $rq .= '`traps_exec_interval`, ';
        if (isset($ret['traps_exec_interval']) && $ret['traps_exec_interval'] != null) {
            $sqlValue .= ':traps_exec_interval, ';
            $retValue[':traps_exec_interval'] = $ret['traps_exec_interval'];
        } else {
            $sqlValue .= 'NULL, ';
        }

        $rq .= '`traps_exec_interval_type`, ';
        if (isset($ret['traps_exec_interval_type']['traps_exec_interval_type'])
            && $ret['traps_exec_interval_type']['traps_exec_interval_type'] != null) {
            $sqlValue .= ':traps_exec_interval_type, ';
            $retValue[':traps_exec_interval_type'] = $ret['traps_exec_interval_type']['traps_exec_interval_type'];
        } else {
            $sqlValue .= "'0', ";
        }

        $rq .= '`traps_exec_method`, ';
        if (isset($ret['traps_exec_method']['traps_exec_method'])
            && $ret['traps_exec_method']['traps_exec_method'] != null) {
            $sqlValue .= ':traps_exec_method, ';
            $retValue[':traps_exec_method'] = $ret['traps_exec_method']['traps_exec_method'];
        } else {
            $sqlValue .= "'0', ";
        }

        $rq .= '`traps_mode`, ';
        if (isset($ret['traps_mode']['traps_mode'])
            && $ret['traps_mode']['traps_mode'] != null) {
            $sqlValue .= ':traps_mode, ';
            $retValue[':traps_mode'] = $ret['traps_mode']['traps_mode'];
        } else {
            $sqlValue .= "'0', ";
        }

        $rq .= '`traps_downtime`, ';
        if (isset($ret['traps_downtime']['traps_downtime'])
            && $ret['traps_downtime']['traps_downtime'] != null) {
            $sqlValue .= ':traps_downtime, ';
            $retValue[':traps_downtime'] = $ret['traps_downtime']['traps_downtime'];
        } else {
            $sqlValue .= "'0', ";
        }

        $rq .= '`traps_output_transform`, ';
        if (isset($ret['traps_output_transform']) && $ret['traps_output_transform'] != null) {
            $sqlValue .= ':traps_output_transform, ';
            $retValue[':traps_output_transform'] = $ret['traps_output_transform'];
        } else {
            $sqlValue .= 'NULL, ';
        }

        $rq .= '`traps_advanced_treatment_default`, ';
        if (isset($ret['traps_advanced_treatment_default']) && $ret['traps_advanced_treatment_default'] != null) {
            $sqlValue .= ':traps_advanced_treatment_default, ';
            $retValue[':traps_advanced_treatment_default'] = $ret['traps_advanced_treatment_default'];
        } else {
            $sqlValue .= "'0', ";
        }

        $rq .= '`traps_timeout`, ';
        if (isset($ret['traps_timeout']) && $ret['traps_timeout'] != null) {
            $sqlValue .= ':traps_timeout, ';
            $retValue[':traps_timeout'] = $ret['traps_timeout'];
        } else {
            $sqlValue .= 'NULL, ';
        }

        $rq .= '`traps_customcode` ';
        if (isset($ret['traps_customcode']) && $ret['traps_customcode'] != null) {
            $sqlValue .= ':traps_customcode ';
            $retValue[':traps_customcode'] = $ret['traps_customcode'];
        } else {
            $sqlValue .= 'NULL ';
        }
        $rq .= ') VALUES (' . $sqlValue . ')';

        $stmt = $this->db->prepare($rq);
        foreach ($retValue as $key => $value) {
            $stmt->bindValue($key, $value);
        }
        $stmt->execute();

        $res = $this->db->query('SELECT MAX(traps_id) FROM traps');
        $traps_id = $res->fetch();

        $this->setMatchingOptions($traps_id['MAX(traps_id)']);
        $this->setServiceRelations($traps_id['MAX(traps_id)']);
        $this->setServiceTemplateRelations($traps_id['MAX(traps_id)']);
        $this->setPreexec($traps_id['MAX(traps_id)']);

        // Prepare value for changelog
        $fields = CentreonLogAction::prepareChanges($ret);
        $this->centreon->CentreonLogAction->insertLog(
            'traps',
            $traps_id['MAX(traps_id)'],
            $fields['traps_name'],
            'a',
            $fields
        );

        return $traps_id['MAX(traps_id)'];
    }

    /**
     * Get pre exec commands from trap_id
     *
     * @param int $trapId
     *
     * @throws PDOException
     * @return array
     */
    public function getPreexecFromTrapId(int $trapId)
    {
        if ($trapId > 0) {
            $query = '
                SELECT tpe_string
                FROM traps_preexec
                WHERE trap_id = :trapId
                ORDER BY tpe_order';

            $statement = $this->db->prepare($query);
            $statement->bindValue(':trapId', $trapId, PDO::PARAM_INT);
            $statement->execute();

            $arr = [];
            $i = 0;
            while ($row = $statement->fetch(PDO::FETCH_ASSOC)) {
                $arr[$i] = ['preexec_#index#' => $row['tpe_string']];
                $i++;
            }

            return $arr;
        }

        return [];
    }

    /**
     * Get matching rules from trap_id
     *
     * @param int $trapId
     *
     * @throws PDOException
     * @return array
     */
    public function getMatchingRulesFromTrapId(int $trapId)
    {
        if ($trapId > 0) {
            $query = '
                SELECT tmo_string, tmo_regexp, tmo_status, severity_id
                FROM traps_matching_properties
                WHERE trap_id = :trapId
                ORDER BY tmo_order';

            $statement = $this->db->prepare($query);
            $statement->bindValue(':trapId', $trapId, PDO::PARAM_INT);
            $statement->execute();

            $arr = [];
            $i = 0;
            while ($row = $statement->fetch(PDO::FETCH_ASSOC)) {
                $arr[$i] = ['rule_#index#' => $row['tmo_string'], 'regexp_#index#' => $row['tmo_regexp'], 'rulestatus_#index#' => $row['tmo_status'], 'ruleseverity_#index#' => $row['severity_id']];
                $i++;
            }

            return $arr;
        }

        return [];
    }

    /**
     * @param int $field
     *
     * @return array
     */
    public static function getDefaultValuesParameters($field)
    {
        $parameters = [];
        $parameters['currentObject']['table'] = 'traps';
        $parameters['currentObject']['id'] = 'traps_id';
        $parameters['currentObject']['name'] = 'traps_name';
        $parameters['currentObject']['comparator'] = 'traps_id';

        switch ($field) {
            case 'manufacturer_id':
                $parameters['type'] = 'simple';
                $parameters['externalObject']['table'] = 'traps_vendor';
                $parameters['externalObject']['id'] = 'id';
                $parameters['externalObject']['name'] = 'name';
                $parameters['externalObject']['comparator'] = 'id';
                break;
            case 'groups':
                $parameters['type'] = 'relation';
                $parameters['externalObject']['table'] = 'traps';
                $parameters['externalObject']['id'] = 'traps_id';
                $parameters['externalObject']['name'] = 'traps_name';
                $parameters['externalObject']['comparator'] = 'traps_id';
                $parameters['relationObject']['table'] = 'traps_group_relation';
                $parameters['relationObject']['field'] = 'traps_id';
                $parameters['relationObject']['comparator'] = 'traps_group_id';
                break;
            case 'services':
                $parameters['type'] = 'relation';
                $parameters['externalObject']['object'] = 'centreonService';
                $parameters['relationObject']['table'] = 'traps_service_relation';
                $parameters['relationObject']['field'] = 'service_id';
                $parameters['relationObject']['comparator'] = 'traps_id';
                break;
            case 'service_templates':
                $parameters['type'] = 'relation';
                $parameters['externalObject']['object'] = 'centreonServicetemplates';
                $parameters['relationObject']['table'] = 'traps_service_relation';
                $parameters['relationObject']['field'] = 'service_id';
                $parameters['relationObject']['comparator'] = 'traps_id';
                break;
        }

        return $parameters;
    }

    /**
     * @param array $values
     * @param array $options
     *
     * @throws PDOException
     * @return array
     */
    public function getObjectForSelect2($values = [], $options = [])
    {
        $items = [];
        $listValues = '';
        $queryValues = [];
        if (! empty($values)) {
            foreach ($values as $k => $v) {
                $listValues .= ':traps' . $v . ',';
                $queryValues['traps' . $v] = (int) $v;
            }
            $listValues = rtrim($listValues, ',');
        } else {
            $listValues .= '""';
        }

        // get list of selected traps
        $query = 'SELECT traps_id, traps_name FROM traps '
            . 'WHERE traps_id IN (' . $listValues . ') ORDER BY traps_name ';

        $stmt = $this->db->prepare($query);
        if ($queryValues !== []) {
            foreach ($queryValues as $key => $id) {
                $stmt->bindValue(':' . $key, $id, PDO::PARAM_INT);
            }
        }
        $stmt->execute();

        while ($row = $stmt->fetch()) {
            $items[] = ['id' => $row['traps_id'], 'text' => $row['traps_name']];
        }

        return $items;
    }

    /**
     * Set preexec commands
     *
     * @param int $trapId
     *
     * @throws PDOException
     */
    protected function setPreexec(int $trapId)
    {
        if ($trapId > 0) {
            $query = 'DELETE FROM traps_preexec WHERE trap_id = :trapId';
            $statement = $this->db->prepare($query);
            $statement->bindValue(':trapId', $trapId, PDO::PARAM_INT);
            $statement->execute();

            $insertStr = '';
            if (isset($_REQUEST['preexec'])) {
                $preexec = $_REQUEST['preexec'];
                $i = 1;
                $queryValues = [];
                foreach ($preexec as $key => $value) {
                    if (is_null($value) || $value == '' || filter_var($key, FILTER_VALIDATE_INT) === false) {
                        continue;
                    }
                    $queryValues[':value' . $key] = [
                        PDO::PARAM_STR => $value,
                    ];
                    if ($insertStr) {
                        $insertStr .= ', ';
                    }
                    $insertStr .= '(:trapId, :value' . $key . ", {$i})";
                    $i++;
                }
            }
            if ($insertStr) {
                $query = "INSERT INTO traps_preexec (trap_id, tpe_string, tpe_order) VALUES {$insertStr}";
                $statement = $this->db->prepare($query);
                $statement->bindValue(':trapId', $trapId, PDO::PARAM_INT);
                if (isset($queryValues)) {
                    foreach ($queryValues as $bindId => $bindData) {
                        foreach ($bindData as $bindType => $bindValue) {
                            $statement->bindValue($bindId, $bindValue, $bindType);
                        }
                    }
                }
                $statement->execute();
            }
        }
    }

    /**
     * Delete & insert service relations
     *
     * @param int $trapId
     *
     * @throws InvalidArgumentException
     * @throws PDOException
     */
    protected function setServiceRelations(int $trapId)
    {
        if ($trapId > 0) {
            $query = "
                DELETE FROM traps_service_relation
                    WHERE traps_id = :trapId
                    AND NOT EXISTS (
                        SELECT s.service_id
                        FROM service s
                        WHERE s.service_register = '0'
                        AND s.service_id = traps_service_relation.service_id)
                    AND NOT EXISTS (
                        SELECT hsr.service_service_id
                        FROM host_service_relation hsr
                        WHERE hsr.hostgroup_hg_id IS NOT NULL
                        AND hsr.service_service_id = traps_service_relation.service_id)";

            $statement = $this->db->prepare($query);
            $statement->bindValue(':trapId', $trapId, PDO::PARAM_INT);
            $statement->execute();

            $services = CentreonUtils::mergeWithInitialValues($this->form, 'services');
            $insertStr = '';
            $first = true;
            $already = [];
            foreach ($services as $id) {
                $t = preg_split("/\-/", $id);
                if (! isset($already[$t[1]])) {
                    if (! $first) {
                        $insertStr .= ',';
                    } else {
                        $first = false;
                    }
                    $insertStr .= '(:trapId, ' . (int) $t[1] . ')';
                    $already[$t[1]] = true;
                }
            }
            if ($insertStr) {
                $query = "INSERT INTO traps_service_relation (traps_id, service_id) VALUES {$insertStr}";
                $statement = $this->db->prepare($query);
                $statement->bindValue(':trapId', $trapId, PDO::PARAM_INT);
                $statement->execute();
            }
        }
    }

    /**
     * Delete & insert service template relations
     *
     * @param int $trapId
     *
     * @throws PDOException
     */
    protected function setServiceTemplateRelations(int $trapId)
    {
        if ($trapId > 0) {
            $query = "
                DELETE FROM traps_service_relation
                WHERE traps_id = :trapId
                AND NOT EXISTS (SELECT s.service_id
                    FROM service s
                    WHERE s.service_register = '1'
                    AND s.service_id = traps_service_relation.service_id)";

            $statement = $this->db->prepare($query);
            $statement->bindValue(':trapId', $trapId, PDO::PARAM_INT);
            $statement->execute();

            $serviceTpl = (array) $this->form->getSubmitValue('service_templates');
            $insertStr = '';
            $first = true;
            foreach ($serviceTpl as $tpl) {
                if (! $first) {
                    $insertStr .= ',';
                } else {
                    $first = false;
                }
                $insertStr .= "(:trapId, {$tpl})";
            }
            if ($insertStr) {
                $query = "INSERT INTO traps_service_relation (traps_id, service_id) VALUES {$insertStr}";
                $statement = $this->db->prepare($query);
                $statement->bindValue(':trapId', $trapId, PDO::PARAM_INT);
                $statement->execute();
            }
        }
    }

    /**
     *  _setMatchingOptions takes the $_POST array and analyses it,
     *  then inserts data into the  traps_matching_properties
     *
     * @param int $trapId
     * @throws PDOException
     * @return void
     */
    private function setMatchingOptions(int $trapId): void
    {
        if ($trapId > 0) {
            $query = 'DELETE FROM traps_matching_properties WHERE trap_id = :trapId';
            $statement = $this->db->prepare($query);
            $statement->bindValue(':trapId', $trapId, PDO::PARAM_INT);
            $statement->execute();

            $insertStr = '';
            if (isset($_REQUEST['rule'])) {
                $rules = $_REQUEST['rule'];
                $regexp = $_REQUEST['regexp'];
                $status = $_REQUEST['rulestatus'];
                $severity = $_REQUEST['ruleseverity'];
                $i = 1;
                $queryValues = [];
                foreach ($rules as $key => $value) {
                    if (is_null($value) || $value == '' || filter_var($key, FILTER_VALIDATE_INT) === false) {
                        continue;
                    }
                    $value = HtmlAnalyzer::sanitizeAndRemoveTags($value);
                    $regexp[$key]
                        = HtmlAnalyzer::sanitizeAndRemoveTags($regexp[$key])
                        ? $regexp[$key]
                        : '';
                    $status[$key] = filter_var($status[$key], FILTER_VALIDATE_INT) ? (int) $status[$key] : 0;
                    $severity[$key] = filter_var($severity[$key], FILTER_VALIDATE_INT);

                    if ($insertStr) {
                        $insertStr .= ', ';
                    }

                    $queryValues[':value' . $key] = [
                        PDO::PARAM_STR => $value,
                    ];
                    $queryValues[':regexp' . $key] = [
                        PDO::PARAM_STR => $regexp[$key],
                    ];
                    $queryValues[':status' . $key] = [
                        PDO::PARAM_INT => $status[$key],
                    ];

                    if ($severity[$key] !== false) {
                        $bindSeverity = ':severity' . $key;
                        $queryValues[':severity' . $key] = [
                            PDO::PARAM_INT => $severity[$key],
                        ];
                    } else {
                        $bindSeverity = 'NULL';
                    }
                    $insertStr .= '(:trapId,  :value' . $key . ', :regexp' . $key . ', :status' . $key . ', '
                        . $bindSeverity . ', ' . $i . ')';
                }

            }
            if ($insertStr) {
                $query = "INSERT INTO traps_matching_properties
                    (trap_id, tmo_string, tmo_regexp, tmo_status, severity_id, tmo_order) VALUES {$insertStr}";
                $statement = $this->db->prepare($query);
                $statement->bindValue(':trapId', $trapId, PDO::PARAM_INT);
                if (isset($queryValues)) {
                    foreach ($queryValues as $bindId => $bindData) {
                        foreach ($bindData as $bindType => $bindValue) {
                            $statement->bindValue($bindId, $bindValue, $bindType);
                        }
                    }
                }
                $statement->execute();
            }
        }
    }
}
