<?php
if (!defined('BASEPATH')) exit('No direct script access allowed');
//Load global Cf_RestInstanse object
require dirname(__FILE__) . '/Cf_RestInstance.php';
// Code here is run before ALL controllers
// BOOTSTRAP CODES
class cf_base_controller extends MX_Controller
{
    public $data;
    var $restClient = null;
    private static $cf_instance;

    function __construct()
    {

        parent::__construct();
        self::$cf_instance = & $this;
        //for replication to work and specifies if this is the primary hub
        initializeHub();
        if (CLI === false)
        {
            $this->setRestClient();
            $this->load->library(array(
                'session',
                'ion_auth',
                'carabiner',
                'user_agent',
                'setting_lib',
                'log_maintenance',
                'cf_hooks'
            ));
            $this->lang->load('tooltip');
            $this->load->helper(array(
                'url',
                'html',
                'language',
                'array'
            ));
            $this->load->model(array(
                'api_rest_model',
                'apps_model'
            ));
            // set timeout cookie, so we will be able to get it from JS without script
            // Don't update cookie for AJAX requests.
            if (!is_ajax())
            {
                $this->_setSessionTimeCookies();
            }

            $this->lang->load('cf_message');
            $this->initialize();
            $this->load->driver('cache', ['adapter' => 'file']);

            apache_note('username', $this->session->userdata('username'));
        }
    }

    public static function &get_Cf_instance()
    {
        return self::$cf_instance;
    }

    function initialize()
    {
        $this->ion_auth->setRestClient($this->getRestClient());
        defined('CFE_MP_BOOTSTRAP') or define('CFE_MP_BOOTSTRAP', true);
    }

    function getProductName()
    {
        try
        {
            $data = $this->api_rest_model->get_api_details();
            $licenseOwner = !empty($data['license']['owner']) ? $data['license']['owner'] : NULL;
            $enterpriseVersion = !empty($data['enterpriseVersion']) ? $data['enterpriseVersion'] : NULL;
            $uiVersion = !empty($data['uiVersion']) ? $data['uiVersion'] : NULL;
            $coreVersion = !empty($data['coreVersion']) ? $data['coreVersion'] : NULL;

            $cfVersionArray = explode(".", $coreVersion);
            $cfMajorMinorVersion = "$cfVersionArray[0]" . "." . "$cfVersionArray[1]";
            $releaseVersion = $cfVersionArray[0] . "." . $cfVersionArray[1]. "." . $cfVersionArray[2];

            defined('HUB_KEY') or define('HUB_KEY', $data['hub']['hostkey'] ?? null);
            defined('CFE_OWNER') or define('CFE_OWNER', $licenseOwner);
            defined('CFE_PRODUCT_NAME') or define('CFE_PRODUCT_NAME', 'CFEngine Enterprise');
            defined('CFE_HUB_VERSION') or define('CFE_HUB_VERSION', $enterpriseVersion);
            defined('CFE_UI_VERSION') or define('CFE_UI_VERSION', $uiVersion);
            defined('CFE_CORE_VERSION') or define('CFE_CORE_VERSION', $coreVersion);
            defined('CFE_MAJOR_MINOR_VERSION') or define('CFE_MAJOR_MINOR_VERSION', $cfMajorMinorVersion);
            defined('CFE_RELEASE_VERSION') or define('CFE_RELEASE_VERSION', $releaseVersion);
            defined(strtoupper($enterpriseVersion)) or define(strtoupper($enterpriseVersion) , true);
        }
        catch(HttpClient_Unauthorized $e)
        {
            redirect('login/index', 'refresh');
        }
        catch(Exception $e)
        {
            show_error($e->getMessage());
        }
    }

    function setRestClientAuthentication()
    {
        $token = $this->session->userdata('access_token') ?? '';
        try
        {
            $this->restClient->setupOauthAuth($token);
            $data = $this->api_rest_model->get_api_details();
        }
        catch(HttpClient_Unauthorized $e)
        {
            if (is_ajax())
            {
                respond_unauthorized('Your session has expired, please log in again.');
                exit;
            }
            else
            {
                redirect('login/index', 'refresh');
            }
        }
        catch(Exception $e)
        {
            log_message(log_level_for_exception($e),$e->getMessage());
            if (is_ajax())
            {
                respond_unauthorized('Your session has expired, please log in again.');
                exit;
            }
            else
            {
                redirect('login/index', 'refresh');
            }
        }
    }

    function setRestClient()
    {
        $apiServer = $this->config->item('rest_server');
        $config = array(
            'base_url' => $apiServer,
            'headers' => array(
                'Cf-Mp-Secret' => $this->config->item('MP_CLIENT_SECRET'),
                'Cf-Real-Ip' => $_SERVER['REMOTE_ADDR']
            )
        );
        $this->load->library('http_client', $config);


        Cf_RestInstance::setRestClient($this->http_client);
        $this->restClient = $this->getRestClient();
    }

    function getRestClient()
    {
        return Cf_RestInstance::getRestClient();
    }
    function custom_404()
    {
        $this->output->set_status_header('404');
        $data = array(
            'title' => $this->lang->line('mission_portal_title') . " - Error" ,
            'title_header' => "error",
        );
        $this->template->load('template', 'errors/404', $data);
    }

    /**
     * Set additional cookie to save time when last request was made and session expiration value
     */
    private function _setSessionTimeCookies()
    {
        $cookie = array(
            'name' => 'CFE_MP_DATA',
            'value' => json_encode(array(
                'LastMPRequest' => getUtcTimestamp() ,
                // session life time in seconds, we have to - sess_time_to_update because if some actions happened in frontend, but session wasn't updated since that time - session will expire faster than JS will know about that
                'SessionExpiredTimeout' => ($this->config->item('sess_expiration') - $this->config->item('sess_time_to_update'))
            )) ,
            'expire' => $this->config->item('sess_expiration') + time() ,
            'domain' => $this->config->item('cookie_domain') ,
            'path' => $this->config->item('cookie_path') ,
            'prefix' => '', // note: update JS if you add prefix here
            'secure' => false
            // we shouldn't crypt it if we are going to get info from session in JS

        );

        $this->input->set_cookie($cookie);
    }
}

class Cf_Controller extends cf_base_Controller
{

    var $appStatus = null;

    function __construct()
    {
        parent::__construct();

        if (CLI === false)
        {
            if (!$this->ion_auth->logged_in())
            {
                if (is_ajax())
                {
                    respond_unauthorized('Your session has expired, please log in again.');
                    exit;
                }
                else
                {
                    //It needs to write cookie through JS, because PHP cannot read URL #hashtag info.
                    echo '<script>
                            document.cookie = "url_to_redirect_after_login=" + document.location.pathname.replace("/index.php", "") + document.location.hash +";path=/;";
                            document.location.href = "/login/index";
                            </script>';
                    exit;
                }
            }
            else if ($this->ion_auth->logged_in() && $this->session->userdata('defaultadmin') && uri_string()!="auth/change_password" && uri_string()!="login/logout")
            {
                // show change password screen in case of default admin/admin user
                redirect('login/change_default', 'refresh');
            }
            else
            {
                $this->setRestClientAuthentication();

                $this->ion_auth->setRestClient($this->getRestClient());
                $this->getProductName();
            }

            $bootstrapTourJs = [
                [ 'node_modules/bootstrap-tour/build/js/bootstrap-tour.min.js' ],
                [ 'bootstrap-tour.js' ]
            ];

            $this->carabiner->js( $bootstrapTourJs, $bootstrapTourJs, TRUE, TRUE, 'footer');
            $this->carabiner->css(
                [[
                    '../../../scripts/node_modules/bootstrap-tour/build/css/bootstrap-tour.min.css'
                ]]
            );
        }
    }
}

class Cli_Controller extends Cf_Controller
{
    public $data = [];

    function __construct()
    {
        parent::__construct();
        if (CLI === false) {
            throw new Exception("You must run this in CLI mode");
        }

    }

    protected function parseVariables()
    {
        $argv = $_SERVER['argv'];
        if (count($argv) > 0) {
            foreach ($argv as $var) {
                $data = explode('=', $var);
                $varName = substr($data[0], 2);
                $this->data[$varName] = $var == $data[0] ? true : str_replace($data[0] . '=', '', $var);
            }
        }
    }

    protected function authorizePestByCFRobot(){
        $this->load->config('cf_robot');
        $config = array(
            'base_url' => $this->config->item('cli_rest_server_url')
        );
        $this->load->library('http_client', $config);
        $this->http_client->setupAuth('CFE_ROBOT', $this->config->item('CFE_ROBOT_PASSWORD'));
        Cf_RestInstance::setRestClient($this->http_client);
    }
}

/**
 *
 * This is and analog of get_instanse function from CI core
 * Return single instanse of Cf_controller. We extend all controllers from it.
 *
 * @return <object>
 *
 */

function &get_Cf_instance()
{
    return Cf_Controller::get_Cf_instance();
}
?>