<?php

/**
 * Vvveb
 *
 * Copyright (C) 2020  Ziadin Givan
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as
 * published by the Free Software Foundation, either version 3 of the
 * License, or (at your option) any later version.
 *
 * 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 Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <https://www.gnu.org/licenses/>.
 *
 */

namespace Vvveb\System;

define('VERSION', '0.1');
//define('DIR_APP', DIR_ROOT . 'app/');
//define('DIR_WEBROOT', DIR_ROOT . 'webroot/');
define('DIR_STORAGE', DIR_ROOT . 'storage/');
define('DIR_CACHE', DIR_ROOT . 'storage/cache/');
define('DIR_PLUGINS', DIR_ROOT . 'plugins/');
define('DIR_COMPILED_TEMPLATES', DIR_STORAGE . 'compiled-templates/');
define('DIR_THEMES', DIR_ROOT . 'public/themes/');

if (APP == 'app') {
	//define('THEME', 'essence');
	define('DIR_THEME', DIR_ROOT . 'public/themes/');
	define('DIR_WEBROOT', DIR_ROOT . 'public/');
} else {
	//define('THEME', 'default');
	define('DIR_THEME', DIR_ROOT . 'public/' . APP . '/themes/');
	define('DIR_WEBROOT', DIR_ROOT . 'public/');
}

define('DIR_APP', DIR_ROOT . APP . '/');
define('DIR_TEMPLATE', DIR_APP . 'template/');
define('DIR_MEDIA', DIR_ROOT . 'public/media/');

include DIR_SYSTEM . 'session.php';

include DIR_SYSTEM . 'service.php';

require_once DIR_SYSTEM . 'frontcontroller.php';

require_once DIR_SYSTEM . 'view.php';

require_once DIR_SYSTEM . 'functions.php';
//require_once(DIR_SYSTEM . 'component.inc');

function logError($message) {
	return error_log($message);
}

function regenerateSQL($sqlFile, $file) {
	$sqlp = new SqlP();

	$sqlp->parseSqlPfile($sqlFile);

	file_put_contents($file, "<?php \n" . $sqlp->generateModel());
}

function autoload($class) {
	// project-specific namespace prefix
	$prefix = 'Vvveb\\';

	// does the class use the namespace prefix?
	$len = strlen($prefix);

	if (strncmp($prefix, $class, $len) !== 0) {
		// no, move to the next registered autoloader
		return;
	}

	$relativeClass = substr($class, $len);

	// replace the namespace prefix with the base directory, replace namespace
	// separators with directory separators in the relative class name, append
	// with .inc
	$root = DIR_APP;

	$isSql = false;
	//if namespace is Vvveb\System load from system dir above app dir
	if (substr_compare($relativeClass, 'System\\', 0, 7) == 0) {
		$root = DIR_ROOT;
	}

	$file = $root . str_replace('\\', '/', strtolower($relativeClass)) . '.php';

	//check if sql files are changed to regenerate sql class
	if (SQL_CHECK && $isSql = (substr_compare($relativeClass, 'SQL', -3, 3) === 0)) {
		//convert camelCase to snake_case
		$sqlFile = strtolower(preg_replace('/(?<!^)[A-Z]/', '_$0', basename(str_replace('\\', '/', substr($relativeClass, 0, -3)))));

		$sqlFile = DIR_SQL . $sqlFile . '.sql';
		$file    = $root . 'model/' . basename(str_replace('\\', '/', strtolower($relativeClass))) . '.php';

		//if the file has not been generated yet or sql files is changed recompile
		if (! file_exists($file) || (filemtime($sqlFile) > filemtime($file))) {
			regenerateSQL($sqlFile, $file);
		}
	}

	// if the file exists, require it
	if (file_exists($file)) {
		require_once $file;
	}
}

spl_autoload_register('Vvveb\System\autoload');

require DIR_ROOT . '/vendor/autoload.php';

function start() {
	//define('DIR_THEME', DIR_ROOT . 'public/themes/'. THEME .'/');

	//start session
	Session :: getInstance();

	//$plugins = new Plugins();
	//$plugins->loadPlugins();

	Extensions\Plugins :: loadPlugins();
	//include(DIR_ROOT . '/plugins/test/plugin.php');

	FrontController::dispatch();
}

function exceptionHandler($exception) {
	/*
	$class= get_class($exception);
	
	switch ($class) {
		case 'mysqli_sql_exception':
				switch ($exception->getCode()) {
					//unknown database
					case 1049:
					break;
				}
		break;
	}
	*/
	$file   = $exception->getFile();
	$lineNo = $exception->getLine() - 1;
	//$code = $exception->getCode();

	$codeLines = file($file);
	$line      = implode("\n", array_slice($codeLines, $lineNo, 1));
	$before    = implode("\n", array_slice($codeLines, $lineNo - 6, 5));
	$after     = implode("\n", array_slice($codeLines, $lineNo + 1, 5));
	$code      = "$before<b>$line</b>$after";
	$lines     = array_slice($codeLines, $lineNo - 7, 14);

	$message = [
		'message' => $exception->getMessage(),
		'code'    => $code,
		'file'    => $file,
		'line_no' => $lineNo,
		'line'    => $line,
		'lines'   => $lines,
		'trace'   => $exception->getTraceAsString(),
	];

	return FrontController::notFound(false, 500, $message);
	echo '<b>Exception:</b> ' . $exception->getMessage();
}

set_exception_handler('Vvveb\System\exceptionHandler');

$dbDefault  = \Vvveb\config('db.default', 'default');
$connection = \Vvveb\config('db.connections.' . $dbDefault,  []);

if ($connection) {
	// Define default database configuration
	define('DB_ENGINE', $connection['engine']);
	define('DB_HOST', $connection['host']);
	define('DB_USER', $connection['user']);
	define('DB_PASS', $connection['password']);
	define('DB_NAME', $connection['database']);
	define('DB_PREFIX', $connection['prefix']);

	define('DIR_SQL', DIR_APP . 'sql/' . DB_ENGINE . '/');
}
