<?php
// phpcs:disable Squiz.NamingConventions.ValidVariableName.MemberNotCamelCaps
/**
 * Controller for collections
 *
 * @category   Controller
 * @package    Pandora FMS
 * @subpackage Community
 * @version    1.0.0
 * @license    See below
 *
 *    ______                 ___                    _______ _______ ________
 *   |   __ \.-----.--.--.--|  |.-----.----.-----. |    ___|   |   |     __|
 *  |    __/|  _  |     |  _  ||  _  |   _|  _  | |    ___|       |__     |
 * |___|   |___._|__|__|_____||_____|__| |___._| |___|   |__|_|__|_______|
 *
 * ============================================================================
 * Copyright (c) 2005-2022 Artica Soluciones Tecnologicas
 * Please see http://pandorafms.org for full contribution list
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation for version 2.
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * ============================================================================
 */

// Begin.
global $config;

// Necessary classes for extends.
require_once $config['homedir'].'/include/class/HTML.class.php';
require_once $config['homedir'].'/include/functions_servers.php';
enterprise_include_once('include/functions_satellite.php');
enterprise_include_once('include/functions_collection.php');

/**
 * Class SatelliteCollection
 */
class SatelliteCollection extends HTML
{

    /**
     * Allowed methods to be called using AJAX request.
     *
     * @var array
     */
    public $AJAXMethods = [
        'draw',
        'addCollection',
        'deleteCollection',
        'loadModal',
    ];

    /**
     * Ajax page.
     *
     * @var string
     */
    private $ajaxController;


    /**
     * Class constructor
     *
     * @param string $ajaxController Ajax controller.
     */
    public function __construct(string $ajaxController)
    {
        global $config;

        check_login();

        if (check_acl($config['id_user'], 0, 'PM') === false
            && is_user_admin($config['id_user']) === true
        ) {
            db_pandora_audit(
                AUDIT_LOG_ACL_VIOLATION,
                'Trying to access Satellite agents'
            );
            include 'general/noaccess.php';
            return;
        }

        if ((int) $config['license_nms'] === 1) {
            db_pandora_audit(
                AUDIT_LOG_NMS_VIOLATION,
                'Trying to access satellite collections'
            );
            include $config['homedir'].'/general/noaccess.php';
            return;
        }

        // Set the ajax controller.
        $this->ajaxController = $ajaxController;
        // Capture all parameters before start.
        $this->satellite_server = (int) get_parameter('server_remote');
        if ($this->satellite_server !== 0) {
            $this->satellite_name = servers_get_name($this->satellite_server);
            $this->satellite_config = (array) config_satellite_get_config_file($this->satellite_name);
        }
    }


    /**
     * Run view
     *
     * @return void
     */
    public function run()
    {
        // Javascript.
        ui_require_jquery_file('pandora');
        // CSS.
        ui_require_css_file('wizard');
        ui_require_css_file('discovery');

        $this->createBlock();

        // Datatables list.
        try {
            $columns = [
                'name',
                'dir',
                'description',
                'actions',
            ];

            $column_names = [
                __('Name'),
                __('Dir'),
                __('Description'),
                __('Actions'),
            ];

            $this->tableId = 'satellite_collections';

            // Load datatables user interface.
            ui_print_datatable(
                [
                    'id'                  => $this->tableId,
                    'class'               => 'info_table',
                    'style'               => 'width: 99%',
                    'columns'             => $columns,
                    'column_names'        => $column_names,
                    'ajax_url'            => $this->ajaxController,
                    'ajax_data'           => [
                        'method'        => 'draw',
                        'server_remote' => $this->satellite_server,
                    ],
                    'ajax_postprocces'    => 'process_datatables_item(item)',
                    'no_sortable_columns' => [
                        0,
                        1,
                        2,
                        3,
                    ],
                    'search_button_class' => 'sub filter float-right',
                    'form'                => [
                        'inputs' => [
                            [
                                'label' => __('Search'),
                                'type'  => 'text',
                                'name'  => 'filter_search',
                                'class' => 'w400px',
                                'size'  => 12,
                            ],
                        ],
                    ],
                    'filter_main_class'   => 'box-flat white_table_graph fixed_filter_bar',
                ]
            );
        } catch (Exception $e) {
            echo $e->getMessage();
        }

        echo '<div id="aux" class="invisible"></div>';
        echo '<div id="msg" class="invisible"></div>';
        html_print_action_buttons('');

        // Load own javascript file.
        echo $this->loadJS();
    }


    /**
     * Get the data for draw the table.
     *
     * @return void.
     */
    public function draw()
    {
        global $config;

        // Init data.
        $data = [];
        // Count of total records.
        $count = 0;
        // Catch post parameters.
        $start  = get_parameter('start', 0);
        $length = get_parameter('length', $config['block_size']);
        $order = get_datatable_order(true);
        $filters = get_parameter('filter', []);

        try {
            ob_start();

            // Gets all collections (database).
            $collections = collection_get_collections(null, $filters['filter_search']);
            if (empty($collections) === false) {
                $data = $collections;
            }

            // All satellite conf collections.
            foreach ($this->satellite_config as $line) {
                $regex = '/^file_collection\s(\S+)/m';

                if (preg_match($regex, $line, $matches, PREG_OFFSET_CAPTURE, 0) > 0) {
                    $key = array_search($matches[1][0], array_column($data, 'short_name'));
                    if ($key !== false) {
                        $data[$key]['delete'] = true;
                    }
                }
            }

            if (empty($data) === false) {
                $data = array_reduce(
                    $data,
                    function ($carry, $item) {
                        // Transforms array of arrays $data into an array
                        // of objects, making a post-process of certain fields.
                        $tmp = (object) $item;

                        $delete = (int) isset($tmp->delete);

                        $tmp->dir = $tmp->short_name;

                        $tmp->actions = '';
                        $tmp->actions .= html_print_image(
                            ($delete === 0) ? 'images/add.png' : 'images/delete.svg',
                            true,
                            [
                                'border'  => '0',
                                'class'   => 'action_button_img mrgn_lft_05em invert_filter',
                                'onclick' => ($delete === 0)
                                    ? 'add_collection(\''.$tmp->short_name.'\')'
                                    : 'delete_collection(\''.$tmp->short_name.'\')',
                            ]
                        );

                        $carry[] = $tmp;
                        return $carry;
                    }
                );
            }

            if (empty($data) === true) {
                $total = 0;
                $data = [];
            } else {
                $total = count($data);
                $data = array_slice($data, $start, $length, false);
            }

            echo json_encode(
                [
                    'data'            => $data,
                    'recordsTotal'    => $total,
                    'recordsFiltered' => $total,
                ]
            );
            // Capture output.
            $response = ob_get_clean();
        } catch (Exception $e) {
            echo json_encode(['error' => $e->getMessage()]);
            exit;
        }

        // If not valid, show error with issue.
        json_decode($response);
        if (json_last_error() === JSON_ERROR_NONE) {
            // If valid dump.
            echo $response;
        } else {
            echo json_encode(
                ['error' => $response]
            );
        }

        exit;
    }


    /**
     * Add collection to satellite conf.
     *
     * @return void
     */
    public function addCollection()
    {
        $short_name = get_parameter('short_name');

        if ($this->parseSatelliteConf('add', $short_name) === false) {
            $this->ajaxMsg('error', __('Error adding collection'));
        } else {
            $this->ajaxMsg('result', _('Collection '.$short_name.' added.'));
        }

        exit;
    }


    /**
     * Delete collection to satellite conf.
     *
     * @return void
     */
    public function deleteCollection()
    {
        $short_name = get_parameter('short_name');

        if ($this->parseSatelliteConf('delete', $short_name) === false) {
            $this->ajaxMsg('error', __('Error deleting collection'));
        } else {
            $this->ajaxMsg('result', _('Collection '.$short_name.' deleted.'));
        }

        exit;
    }


    /**
     * Parse satellite configuration .
     *
     * @param string $action     Action to perform (add, delete).
     * @param string $short_name Short name.
     *
     * @return boolean
     */
    private function parseSatelliteConf(string $action, string $short_name)
    {
        switch ($action) {
            case 'delete':
                $pos = preg_grep('/^file_collection '.$short_name.'/', $this->satellite_config);
                if (empty($pos) === false) {
                    $key_pos = 0;
                    foreach ($pos as $key => $value) {
                        $key_pos = $key;
                        break;
                    }

                    unset($this->satellite_config[$key_pos]);
                }

                $conf = implode('', $this->satellite_config);
            break;

            default:
            case 'add':
                $pos = preg_grep('/^file_collection/', $this->satellite_config);
                if (empty($pos) === false) {
                    $string_collection = 'file_collection '.$short_name."\n";

                    $key_pos = array_keys($pos)[(count($pos) - 1)];
                    $array1 = array_slice($this->satellite_config, 0, ($key_pos + 1));
                    $array2 = array_slice($this->satellite_config, ($key_pos + 1));
                    $array_merge = array_merge($array1, [$string_collection], $array2);
                    $this->satellite_config = $array_merge;

                    // Check config.
                    if (empty($this->satellite_config) === true) {
                        return false;
                    }
                } else {
                    $pos = preg_grep('/^\#\sFile\scollections/', $this->satellite_config);
                    $string_collection = 'file_collection '.$short_name."\n";

                    $key_pos = 0;
                    foreach ($pos as $key => $value) {
                        $key_pos = $key;
                        break;
                    }

                    $key_pos++;

                    $array1 = array_slice($this->satellite_config, 0, $key_pos);
                    $array2 = array_slice($this->satellite_config, $key_pos);
                    // Add collection to conf.
                    $array_merge = array_merge($array1, [$string_collection], $array2);
                    $this->satellite_config = $array_merge;

                    // Check config.
                    if (empty($this->satellite_config) === true) {
                        return false;
                    }
                }

                $conf = implode('', $this->satellite_config);
            break;
        }

        return $this->saveAgent($conf);
    }


    /**
     * Saves agent to satellite cofiguration file.
     *
     * @param string $new_conf Config file.
     *
     * @return boolean|void
     */
    private function saveAgent(string $new_conf)
    {
        global $config;

        if (empty($new_conf) === true) {
            return false;
        }

        db_pandora_audit(
            AUDIT_LOG_SYSTEM,
            'Update remote config for server '.$this->satellite_name
        );

        // Convert to config file encoding.
        $encoding = config_satellite_get_encoding($new_conf);
        if ($encoding !== false) {
            $converted_server_config = mb_convert_encoding($new_conf, $encoding, 'UTF-8');
            if ($converted_server_config !== false) {
                $new_conf = $converted_server_config;
            }
        }

        // Get filenames.
        if ($this->satellite_server !== false) {
            $files = config_satellite_get_satellite_config_filenames($this->satellite_name);
        } else {
            $files = [];
            $files['conf'] = $config['remote_config'].'/conf/'.md5($this->satellite_name).'.srv.conf';
            $files['md5'] = $config['remote_config'].'/md5/'.md5($this->satellite_name).'.srv.md5';
        }

        // Save configuration.
        $result = file_put_contents($files['conf'], $new_conf);

        if ($result === false) {
            return false;
        }

        // Save configuration md5.
        $result = file_put_contents($files['md5'], md5($new_conf));
    }


    /**
     * Checks if target method is available to be called using AJAX.
     *
     * @param string $method Target method.
     *
     * @return boolean True allowed, false not.
     */
    public function ajaxMethod(string $method)
    {
        return in_array($method, $this->AJAXMethods);
    }


    /**
     * Minor function to dump json message as ajax response.
     *
     * @param string $type Type: result || error.
     * @param string $msg  Message.
     *
     * @return void
     */
    private function ajaxMsg(string $type, string $msg)
    {
        echo json_encode(
            [
                $type => __($msg),
            ]
        );

        exit;
    }


    /**
     * Create file_collections blocks
     *
     * @return void
     */
    public function createBlock()
    {
        $init = preg_grep('/^\#\sFile\scollections/', $this->satellite_config);

        if (empty($init) === true) {
            $collection = "# File collections\n";

            array_push($this->satellite_config, "\n");
            array_push($this->satellite_config, $collection);
            array_push($this->satellite_config, "\n");

            $conf = implode('', $this->satellite_config);
            $this->saveAgent($conf);
        }
    }


    /**
     * Load Javascript code.
     *
     * @return string.
     */
    public function loadJS()
    {
        // Nothing for this moment.
        ob_start();

        // Javascript content.
        ?>
        <script type="text/javascript">
            /**
             * Add collection.
             */
            function add_collection(short_name) {
                $('#aux').empty();
                $('#aux').text('<?php echo __('Are you sure?'); ?>');
                $('#aux').dialog({
                    title: '<?php echo __('Add collection'); ?>',
                    buttons: [{
                            class: 'ui-widget ui-state-default ui-corner-all ui-button-text-only sub upd submit-cancel',
                            text: '<?php echo __('Cancel'); ?>',
                            click: function(e) {
                                $(this).dialog('close');
                            }
                        },
                        {
                            text: 'Add',
                            class: 'ui-widget ui-state-default ui-corner-all ui-button-text-only sub ok submit-next',
                            click: function(e) {
                                $.ajax({
                                    method: 'post',
                                    url: '<?php echo ui_get_full_url('ajax.php', false, false, false); ?>',
                                    data: {
                                        page: 'enterprise/godmode/servers/collections_satellite',
                                        method: 'addCollection',
                                        short_name: short_name,
                                        server_remote: <?php echo $this->satellite_server; ?>,
                                    },
                                    datatype: "json",
                                    success: function(data) {
                                        console.log(data);
                                        showMsg(data);
                                    },
                                    error: function(e) {
                                        showMsg(e);
                                    }
                                });
                            }
                        }
                    ]
                });
            }

            /**
             * Delete collection.
             */
            function delete_collection(short_name) {
                $('#aux').empty();
                $('#aux').text('<?php echo __('Are you sure?'); ?>');
                $('#aux').dialog({
                    title: '<?php echo __('Delete collection'); ?>',
                    buttons: [{
                            class: 'ui-widget ui-state-default ui-corner-all ui-button-text-only sub upd submit-cancel',
                            text: '<?php echo __('Cancel'); ?>',
                            click: function(e) {
                                $(this).dialog('close');
                            }
                        },
                        {
                            text: 'Delete',
                            class: 'ui-widget ui-state-default ui-corner-all ui-button-text-only sub ok submit-next',
                            click: function(e) {
                                $.ajax({
                                    method: 'post',
                                    url: '<?php echo ui_get_full_url('ajax.php', false, false, false); ?>',
                                    data: {
                                        page: 'enterprise/godmode/servers/collections_satellite',
                                        method: 'deleteCollection',
                                        short_name: short_name,
                                        server_remote: <?php echo $this->satellite_server; ?>,
                                    },
                                    datatype: "json",
                                    success: function(data) {
                                        console.log(data);
                                        showMsg(data);
                                    },
                                    error: function(e) {
                                        showMsg(e);
                                    }
                                });
                            }
                        }
                    ]
                });
            }

            /**
            * Process ajax responses and shows a dialog with results.
            */
            function showMsg(data) {
                var title = "<?php echo __('Success'); ?>";
                var dt_satellite_agents = $("#satellite_collections").DataTable();
                dt_<?php echo $this->tableId; ?>.draw(false);

                var text = '';
                var failed = 0;
                try {
                    data = JSON.parse(data);
                    text = data['result'];
                } catch (err) {
                    title =  "<?php echo __('Failed'); ?>";
                    text = err.message;
                    failed = 1;
                }
                if (!failed && data['error'] != undefined) {
                    title =  "<?php echo __('Failed'); ?>";
                    text = data['error'];
                    failed = 1;
                }
                if (data['report'] != undefined) {
                    data['report'].forEach(function (item){
                        text += '<br>'+item;
                    });
                }

                $('#msg').empty();
                $('#msg').html(text);
                $('#msg').dialog({
                    width: 450,
                    position: {
                        my: 'center',
                        at: 'center',
                        of: window,
                        collision: 'fit'
                    },
                    title: title,
                    buttons: [
                        {
                            class: "ui-widget ui-state-default ui-corner-all ui-button-text-only sub ok submit-next",
                            text: 'OK',
                            click: function(e) {
                                if (!failed) {
                                    $(".ui-dialog-content").dialog("close");
                                    $('.info').hide();
                                } else {
                                    $(this).dialog('close');
                                }
                            }
                        }
                    ]
                });
            }
        </script>
        <?php
        // EOF Javascript content.
        return ob_get_clean();
    }


}