<?php

$ConfigFileName = dirname(__FILE__).'/../Config/Config.php';
if (file_exists($ConfigFileName)) include_once($ConfigFileName);

include_once(dirname(__FILE__).'/../Global.php');
include_once(dirname(__FILE__).'/Version.php');
include_once(dirname(__FILE__).'/BaseView.php');
include_once(dirname(__FILE__).'/UpdateTrace.php');
include_once(dirname(__FILE__).'/DefaultConfig.php');

class Core extends System
{
  public array $Pages;
  public bool $ShowPage;
  public string $BaseURL;
  public bool $UseSession;

  function __construct()
  {
    parent::__construct();
    $this->Pages = array();
    $this->UseSession = true;
    $this->ShowPage = true;
    $this->BaseURL = $_SERVER['SCRIPT_NAME'];
    if (substr($this->BaseURL, -10, 10) == '/index.php')
      $this->BaseURL = substr($this->BaseURL, 0, -10);
  }

  function RunCommon(): void
  {
    global $Config, $DatabaseRevision, $WithoutSessionStart;

    if ($this->UseSession) session_start();

    $ErrorHandler = new ErrorHandler();
    $ErrorHandler->ShowError = $Config['Web']['ShowError'];
    //$ErrorHandler->Start();

    try
    {
      $this->Database = new Database();
      $this->Database->Connect($Config['Database']['Host'], $Config['Database']['User'],
        $Config['Database']['Password'], $Config['Database']['Database']);
      $this->Database->Prefix = $Config['Database']['Prefix'];
      $this->Database->charset($Config['Database']['Charset']);
      $this->Database->ShowSQLError = $Config['Web']['ShowSQLError'];
      $this->Database->ShowSQLQuery = $Config['Web']['ShowSQLQuery'];
    } catch (Exception $E) {
    }

    // SQL injection hack protection
    foreach ($_POST as $Index => $Item) $_POST[$Index] = addslashes($Item);
    foreach ($_GET as $Index => $Item) $_GET[$Index] = addslashes($Item);

    $this->Config = &$Config;

    $this->StartModules();
  }

  function StartModules(): void
  {
    $ModuleSetup = $this->ModuleManager->LoadModule(dirname(__FILE__).'/../Packages/Common/Modules/Setup.php');
    $ModuleSetup->Install();
    $ModuleSetup->Start();
    $this->ModuleManager->LoadModules();
    $this->ModuleManager->LoadModule(dirname(__FILE__).'/../Packages/Common/Modules/ModuleManager.php');
    if (file_exists($this->ModuleManager->FileName)) $this->ModuleManager->LoadState();
    if (ModuleSetup::Cast($ModuleSetup)->CheckState())
    {
      $this->ModuleManager->StartAll(array(ModuleCondition::Enabled));
    }
  }

  function Run(): void
  {
    $this->RunCommon();
    if ($this->ShowPage)
    {
      $this->PathItems = ProcessURL();
      $this->ShowPage();
    }
  }

  static function Cast(System $System): Core
  {
    if ($System instanceof Core)
    {
      return $System;
    }
    throw new Exception('Expected Core type but '.gettype($System));
  }

  function ShowPage(): void
  {
    $this->BaseView = new BaseView($this);

    /* @var $Page Page */
    $ClassName = $this->SearchPage($this->PathItems, $this->Pages);
    if ($ClassName != '')
    {
      $Page = new $ClassName($this);
    } else {
      $Page = new PageMissing($this);
    }
    echo($this->BaseView->GetOutput($Page));
  }

  function SearchPage(array $PathItems, array $Pages): string
  {
    if (count($PathItems) > 0) $PathItem = $PathItems[0];
      else $PathItem = '';
    if (array_key_exists($PathItem, $Pages))
    {
      if (is_array($Pages[$PathItem]))
      {
        array_shift($PathItems);
        return $this->SearchPage($PathItems, $Pages[$PathItem]);
      } else return $Pages[$PathItem];
    } else return '';
  }

  function Link(string $Target): string
  {
    return $this->BaseURL.$Target;
  }
}

class PageMissing extends Page
{
  function __construct($System)
  {
    parent::__construct($System);
    $this->ParentClass = '';
    $this->Title = T('Page not found');
  }

  function Show(): string
  {
    Header($_SERVER['SERVER_PROTOCOL'].' 404 Not Found');
    return '<h3 align="center">'.T('Required page not found');
  }
}
