<?php
include_once __DIR__ . '/../models/RandomGenerator.php';
/**
 * Class HostsGenerator
 */
class HostsGenerator extends Cli_Controller
{
    public $schema;
    public $hostKey;
    public $hostCount;
    public $verbose;
    public $interval;
    public $iterations;
    public $failCount;
    public $insertLogs;

    private $cfdb;

    /**
     * HostsGenerator constructor.
     * @throws Exception
     */
    public function __construct()
    {
        parent::__construct();

        $this->parseVariables();
        $this->setVariables();

        $this->cfdb = $this->load->database('cfdb', true);
        $this->cfdb->query('SET session_replication_role = replica;');
        $this->cfdb->query(sprintf("SET schema '%s'", $this->schema));

        $this->load->model('data_generator/host_generate_model');
        $this->host_generate_model->setDb($this->cfdb);

        $this->load->model('data_generator/host_simulate_model');
        $this->host_simulate_model->setDb($this->cfdb);
        $this->host_simulate_model->insertLogs = $this->insertLogs;
    }

    public function __destruct()
    {
        $this->cfdb->query('SET session_replication_role = DEFAULT;');
    }

    private function setVariables()
    {
        $this->schema = isset($this->data['schema']) ? $this->data['schema'] : 'public';
        $this->hostCount = isset($this->data['hostCount']) ? $this->data['hostCount'] : 1;
        $this->interval = isset($this->data['interval']) ? $this->data['interval'] : 60;
        $this->iterations = isset($this->data['iterations']) ? $this->data['iterations'] : 10;
        $this->hostKey = isset($this->data['hostKey']) ? $this->data['hostKey'] : RandomGenerator::hostkey();
        $this->verbose = isset($this->data['verbose']) ? $this->data['verbose'] : false;
        $this->failCount = isset($this->data['failCount']) ? $this->data['failCount'] : 0;
        $this->insertLogs = isset($this->data['insertLogs']) ? $this->data['insertLogs'] : false;
    }

    public function generate()
    {
        $this->host_generate_model->generateHosts($this->hostKey, $this->hostCount);
        if ($this->verbose) {
            echo '__hosts were generated' . PHP_EOL;
        }

        $this->host_generate_model->generateLastSeenHosts($this->hostKey, $this->hostCount);
        if ($this->verbose) {
            echo '__lastseenhosts were generated' . PHP_EOL;
        }

        $this->host_generate_model->bulkGenerateContexts($this->hostKey, $this->hostCount);
        if ($this->verbose) {
            echo '__contexts were generated' . PHP_EOL;
        }

        $this->host_generate_model->bulkGenerateVariables($this->hostKey, $this->hostCount);
        if ($this->verbose) {
            echo '__variables were generated' . PHP_EOL;
        }

        $this->host_generate_model->bulkGenerateAgentStatus($this->hostKey, $this->hostCount, $this->failCount);
        if ($this->verbose) {
            echo '__agentstatus were generated' . PHP_EOL;
        }

        $this->host_generate_model->updateContextCache();
        if ($this->verbose) {
            echo 'contextCache was rebuilt' . PHP_EOL;
        }

        if (isset($this->data['withSoftware']) && $this->data['withSoftware'] != 0) {
            for ($i = 1; $i <= $this->hostCount; $i++) {
                $this->host_generate_model->generateSoftware($this->hostKey . $i);
            }
            if ($this->verbose) {
                echo '__software and __softwareupdates were generated' . PHP_EOL;
            }
        }

        if (isset($this->data['withCMDB']) && $this->data['withCMDB'] != 0) {
            for ($i = 1; $i <= $this->hostCount; $i++) {
                $this->host_generate_model->generateCMDB($this->hostKey, $i);
            }
            if ($this->verbose) {
                echo '__cmdb were generated' . PHP_EOL;
            }
        }

        if (isset($this->data['withPromiseExecutions']) && $this->data['withPromiseExecutions'] != 0) {
            for ($i = 1; $i <= $this->hostCount; $i++) {
                $this->host_generate_model->generatePromiseExecutions($this->hostKey . $i);
            }
            if ($this->verbose) {
                echo '__promiseexecutions were generated' . PHP_EOL;
            }
        }

        if (isset($this->data['withPromiseLog']) && $this->data['withPromiseLog'] != 0) {
            for ($i = 1; $i <= $this->hostCount; $i++) {
                $this->host_generate_model->generatePromiseLog($this->hostKey . $i);
            }
            if ($this->verbose) {
                echo '__promiseLog were generated' . PHP_EOL;
            }
        }

        if (isset($this->data['withMeasurements']) && $this->data['withMeasurements'] != 0) {
            for ($i = 1; $i <= $this->hostCount; $i++) {
                $this->host_generate_model->generateMeasurementsData($this->hostKey . $i);
            }
            if ($this->verbose) {
                echo '__monitoringmgmeta and __monitoringmg were generated' . PHP_EOL;
            }
        }

        $this->host_generate_model->updateMaterializedViews();
        if ($this->verbose) {
            echo 'materialized views were refreshed' . PHP_EOL;
        }
    }

    /**
     * @param $hostKey
     * @param $i
     */
    private function createHost($hostKey, $i)
    {
        $this->host_generate_model->generateHost($hostKey);
        $this->host_generate_model->generateVariables($hostKey, $i);
        $this->host_generate_model->generateContexts($hostKey, $i);
        $this->host_generate_model->setNotKept($hostKey, $i);

        if (isset($this->data['withSoftware']) && $this->data['withSoftware'] != 0) {
            $this->host_generate_model->generateSoftware($hostKey);
        }

        if (isset($this->data['withPromiseExecutions']) && $this->data['withPromiseExecutions'] != 0) {
            $this->host_generate_model->generatePromiseExecutions($hostKey);
        }

        if (isset($this->data['withMeasurements']) && $this->data['withMeasurements'] != 0) {
            $this->host_generate_model->generateMeasurementsData($hostKey);
        }

        $status = $i > $this->failCount ? 'OK' : 'FAIL';
        $this->host_generate_model->generateAgentStatus($hostKey, $status);
    }

    public function simulate()
    {
        echo 'Simulation of ' .
            $this->hostCount .
            ' hosts for ' .
            $this->iterations .
            ' iterations, every ' .
            $this->interval .
            ' seconds' .
            PHP_EOL;
        echo 'To finish the simulation press ctrl+c' . PHP_EOL . PHP_EOL;

        for ($iter = 1; $iter <= $this->iterations; $iter++) {
            if ($this->verbose) {
                echo 'Iteration ' . $iter . ' of ' . $this->iterations . ' starting.' . PHP_EOL;
            }

            for ($i = 1; $i <= $this->hostCount; $i++) {
                if ($this->verbose) {
                    $percent = (int) $i / ($this->hostCount / 100);
                    if ($i % 20 == 0) {
                        echo 'Hosts updating: ' . $percent . '%' . PHP_EOL;
                    }
                }

                $hostKey = $this->hostKey . $i;
                if ($this->host_simulate_model->isHostExist($hostKey) === null) {
                    $this->createHost($hostKey, $i);
                }
                $this->host_simulate_model->updateHost($hostKey);
                $this->host_simulate_model->updateVariables($hostKey, $i);
                $this->host_simulate_model->updateContexts($hostKey, $i);
                if (isset($this->data['withSoftware']) && $this->data['withSoftware'] != 0) {
                    $this->host_simulate_model->updateSoftware($hostKey);
                }
                if (isset($this->data['withPromiseExecutions']) && $this->data['withPromiseExecutions'] != 0) {
                    $this->host_simulate_model->updatePromiseExecutions($hostKey);
                }
                if (isset($this->data['withMeasurements']) && $this->data['withMeasurements'] != 0) {
                    $this->host_simulate_model->updateMeasurementsData($hostKey);
                }
                $this->host_simulate_model->updateAgentStatus($hostKey);
                gc_collect_cycles();
            }
            if ($this->verbose) {
                echo 'Hosts data was updated.' . PHP_EOL;
                if ($iter < $this->iterations) {
                    echo 'Next update will be in ' . $this->interval . ' seconds' . PHP_EOL;
                    sleep($this->interval);
                }
            }
        }
    }
}
