<?php
// Autoloader
$autoloader = new \Autoloader();

require_once(DIR_SYSTEM . 'vendor.php');

// Registry
$registry = new \Registry();

// Config
$config = new \Config();
$config->load('default');
$config->load($application_config);
$registry->set('config', $config);

// Log
$log = new \Log($config->get('error_filename'));
$registry->set('log', $log);

date_default_timezone_set($config->get('date_timezone'));

set_error_handler(function($code, $message, $file, $line) use ($log, $config) {
    // error suppressed with @
    if (error_reporting() === 0) {
        return false;
    }

    switch ($code) {
        case E_NOTICE:
        case E_USER_NOTICE:
            $error = 'Notice';
            break;
        case E_WARNING:
        case E_USER_WARNING:
            $error = 'Warning';
            break;
        case E_ERROR:
        case E_USER_ERROR:
            $error = 'Fatal Error';
            break;
        default:
            $error = 'Unknown';
            break;
    }

    if ($config->get('error_display')) {
        echo '<b>' . $error . '</b>: ' . $message . ' in <b>' . $file . '</b> on line <b>' . $line . '</b>';
    }

    if ($config->get('error_log')) {
        $log->write('PHP ' . $error . ':  ' . $message . ' in ' . $file . ' on line ' . $line);
    }

    return true;
});

// Event
$event = new \Event($registry);
$registry->set('event', $event);

// Event Register
if ($config->has('action_event')) {
    foreach ($config->get('action_event') as $key => $value) {
        foreach ($value as $priority => $action) {
            $event->register($key, new \Action($action), $priority);
        }
    }
}

// Loader
$loader = new \Loader($registry);
$registry->set('load', $loader);

// Request
$request = new \Request();
$registry->set('request', $request);

// Response
$response = new \Response();
$registry->set('response', $response);

foreach ($config->get('response_header') as $header) {
    $response->addHeader($header);
}

$response->addHeader('Access-Control-Allow-Origin: *');
$response->addHeader('Access-Control-Allow-Credentials: true');
$response->addHeader('Access-Control-Max-Age: 1000');
$response->addHeader('Access-Control-Allow-Headers: X-Requested-With, Content-Type, Origin, Cache-Control, Pragma, Authorization, Accept, Accept-Encoding');
$response->addHeader('Access-Control-Allow-Methods: PUT, POST, GET, OPTIONS, DELETE');
$response->addHeader('Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0');
$response->addHeader('Pragma: no-cache');
$response->setCompression($config->get('response_compression'));

// Database
if ($config->get('db_autostart')) {
    $db = new \DB($config->get('db_engine'), $config->get('db_hostname'), $config->get('db_username'), $config->get('db_password'), $config->get('db_database'), $config->get('db_port'));
    $registry->set('db', $db);

    // Sync PHP and DB time zones
    $db->query("SET `time_zone` = '" . $db->escape(date('P')) . "'");
}

// Session
if ($config->get('session_autostart')) {
    $session = new \Session($config->get('session_engine'), $registry);
    $registry->set('session', $session);

    if (isset($request->cookie[$config->get('session_name')])) {
        $session_id = $request->cookie[$config->get('session_name')];
    } else {
        $session_id = '';
    }

    $session->start($session_id);

    // Require higher security for session cookies
    $option = [
        'expires'  => 0,
        'path'     => $config->get('session_path'),
        'domain'   => $config->get('session_domain'),
        'secure'   => $request->server['HTTPS'],
        'httponly' => false,
        'SameSite' => $config->get('session_samesite')
    ];

    setcookie($config->get('session_name'), $session->getId(), $option);
}

// Cache
$registry->set('cache', new \Cache($config->get('cache_engine'), $config->get('cache_expire')));

// Url
if ($config->get('url_autostart')) {
    $registry->set('url', new \Url($config->get('site_url'), $config->get('site_ssl')));
}

// Language
$language = new \Language($config->get('language_directory'));
$registry->set('language', $language);

// Document
$registry->set('document', new \Document());

// Config Autoload
if ($config->has('config_autoload')) {
    foreach ($config->get('config_autoload') as $value) {
        $loader->config($value);
    }
}

// Language Autoload
if ($config->has('language_autoload')) {
    foreach ($config->get('language_autoload') as $value) {
        $loader->language($value);
    }
}

// Library Autoload
if ($config->has('library_autoload')) {
    foreach ($config->get('library_autoload') as $value) {
        $loader->library($value);
    }
}

// Model Autoload
if ($config->has('model_autoload')) {
    foreach ($config->get('model_autoload') as $value) {
        $loader->model($value);
    }
}

// Route
$route = new \Router($registry);

// Pre Actions
if ($config->has('action_pre_action')) {
    foreach ($config->get('action_pre_action') as $value) {
        $route->addPreAction(new \Action($value));
    }
}

// Dispatch
$route->dispatch(new \Action($config->get('action_router')), new \Action($config->get('action_error')));

// Output
$response->output();
