<?php

require_once('Config/Config.php');
require_once('Global.php');
require_once('Packages/Common/Common.php');
require_once('View.php');

require_once('Modules/Meet/Meet.php');
require_once('Modules/Meet/MeetPage.php');
require_once('Modules/Dance/Dance.php');
require_once('Modules/Movie/Movie.php');
require_once('Modules/School/School.php');
require_once('Modules/Club/Club.php');
require_once('Modules/Event/Event.php');
require_once('Modules/Event/EventPage.php');

if (isset($_SERVER['REMOTE_ADDR'])) session_start();

class Core extends System
{
  public array $Config;
  public array $PathItems;
  public bool $ShowPage;
  public array $MainMenu;
  public array $PageHeaders;
  public array $Bars;

  function __construct()
  {
    parent::__construct();
    $this->ShowPage = true;
    $this->MainMenu = array();
    $this->PageHeaders = array();
    $this->Bars = array();
  }

  function IsAdmin(): bool
  {
    return array_key_exists('IsAdmin', $_SESSION) and ($_SESSION['IsAdmin'] == 1);
  }

  function Link(string $URL): string
  {
    return $this->Config['BaseURL'].$URL;
  }

  function AbsoluteLink(string $URL): string
  {
    return $this->Config['HostName'].$this->Config['BaseURL'].$URL;
  }

  function ShowMenu(): string
  {
    $Output = '<div>';
    foreach ($this->MainMenu as $MenuItem)
    {
      $Output .= '<a href="'.$this->Link($MenuItem['Link']).'">'.$MenuItem['Title'].'</a> ';
    }
    $Output .= '</div>';
    return $Output;
  }

  function ProcessURL(): array
  {
    if (array_key_exists('REDIRECT_QUERY_STRING', $_SERVER))
      $PathString = $_SERVER['REDIRECT_QUERY_STRING'];
    else $PathString = '';
    if (substr($PathString, -1, 1) == '/') $PathString = substr($PathString, 0, -1);
    $PathItems = explode('/', $PathString);
    if (array_key_exists('REQUEST_URI', $_SERVER) and (strpos($_SERVER['REQUEST_URI'], '?') !== false))
      $_SERVER['QUERY_STRING'] = substr($_SERVER['REQUEST_URI'], strpos($_SERVER['REQUEST_URI'], '?') + 1);
    else $_SERVER['QUERY_STRING'] = '';
    parse_str($_SERVER['QUERY_STRING'], $_GET);
    return $PathItems;
  }

  function RegisterPage($Path, $Handler): void
  {
    if (is_array($Path))
    {
      $Page = &$this->Pages;
      $LastKey = array_pop($Path);
      foreach ($Path as $PathItem)
      {
        $Page = &$Page[$PathItem];
      }
      if (!is_array($Page)) $Page = array('' => $Page);
      $Page[$LastKey] = $Handler;
    } else $this->Pages[$Path] = $Handler;
  }

  function RegisterMenuItem(string $Link, string $Title): void
  {
     $this->MainMenu[] = array('Link' => $Link, 'Title' => $Title);
  }

  function RegisterPageHeader(string $Name, array $Callback): void
  {
    $this->PageHeaders[$Name] = $Callback;
  }

  function RegisterPageBar(string $Name): void
  {
    $this->Bars[$Name] = array();
  }

  function UnregisterPageBar(string $Name): void
  {
    unset($this->Bars[$Name]);
  }

  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 PageNotFound(): string
  {
    return 'Page '.implode('/', $this->PathItems).' not found.';
  }

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

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

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

  function RunCommon(): void
  {
    global $Config;

    $this->Config = $Config;
    $this->Database = new Database();
    $this->Database->Connect($this->Config['Database']['Host'], $this->Config['Database']['User'],
      $this->Config['Database']['Password'], $this->Config['Database']['Database']);
    $this->Database->Prefix = $this->Config['Database']['Prefix'];
    $this->Database->charset($this->Config['Database']['Charset']);
    $this->Database->ShowSQLError = false;
    $this->Database->ShowSQLQuery = false;
    $this->PathItems = $this->ProcessURL();

    $this->RegisterPageBar('Top');
    $this->Name = 'Tanec';
  }

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

class PageMissing extends Page
{
  function __construct($System)
  {
    parent::__construct($System);
    $this->Title = 'Stránka nenalezena';
    $this->ParentClass = 'PagePortal';
  }

  function Show(): string
  {
    Header($_SERVER['SERVER_PROTOCOL'].' 404 Not Found');
    return '<h3 align="center">Požadovaná stránka neexistuje.</h3>';
  }
}

class PageRobots extends Page
{
  function __construct($System)
  {
    parent::__construct($System);
  }

  function Show(): string
  {
    $this->RawPage = true;
    $Result = 'User-agent: *'."\n".
      'Disallow: /*?'."\n".
      'Sitemap: '.$this->System->AbsoluteLink('/sitemap.xml');
    return $Result;
  }
}

class PageSiteMap extends Page
{
  function Show(): string
  {
    $this->RawPage = true;
    $Urls = array(
      '/seznamka/',
      '/skoly/',
      '/tance/',
      '/filmy/',
      '/udalosti/',
    );
    $Result = '<?xml version="1.0" encoding="UTF-8"?>'."\n".
      '<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">'."\n";
    foreach ($Urls as $Url)
    {
      $Result .= '<url>'."\n".
        '  <loc>'.$this->System->AbsoluteLink($Url).'</loc>'."\n".
        //'<lastmod>'..'</lastmod>'."\n".
        '</url>'."\n";
    }

    // Meets
    $DbResult = $this->Database->query('SELECT `Id`,`Time` FROM `MeetItem` WHERE '.GetDefaultMeetFilter());
    while ($DbRow = $DbResult->fetch_array())
    {
      $Url = '/seznamka/inzerat/'.$DbRow['Id'];
      $Time = MysqlDateTimeToTime($DbRow['Time']);
      $Result .= '<url>'."\n".
        '  <loc>'.$this->System->AbsoluteLink($Url).'</loc>'."\n".
        '  <lastmod>'.date('c', $Time).'</lastmod>'."\n".
        '</url>'."\n";
    }

    // Events
    $DbResult = $this->Database->query('SELECT `Id`,`TimeFrom` FROM `Event` WHERE '.GetDefaultEventFilter());
    while ($DbRow = $DbResult->fetch_array())
    {
      $Url = '/udalosti/udalost/'.$DbRow['Id'];
      $Time = MysqlDateTimeToTime($DbRow['TimeFrom']);
      $Result .= '<url>'."\n".
        '  <loc>'.$this->System->AbsoluteLink($Url).'</loc>'."\n".
        '  <lastmod>'.date('c', $Time).'</lastmod>'."\n".
        '</url>'."\n";
    }

    $Result .= '</urlset>';
    return $Result;
  }
}

class PageLogin extends Page
{
  function __construct($System)
  {
    parent::__construct($System);
    $this->Title = 'Přihlášení';
    $this->ParentClass = 'PagePortal';
  }

  function Show(): string
  {
    global $Config;

    $Output = '';
    if (array_key_exists('login', $_GET))
    {
      if (array_key_exists('password', $_POST))
      {
        if ($_POST['password'] == $Config['Web']['AdminPassword'])
        {
          $_SESSION['IsAdmin'] = 1;
          $Output .= 'Úspěšně přihlášen jako správce.';
        } else {
          $_SESSION['IsAdmin'] = 0;
          $Output .= 'Heslo není správné.';
          $Output .= $this->ShowLoginForm();
        }
      } else {
        $Output .= 'Chybí heslo.';
        $Output .= $this->ShowLoginForm();
      }
    } else
    if (array_key_exists('logoff', $_GET))
    {
      $_SESSION['IsAdmin'] = 0;
      $Output .= 'Odhlášení úspěšné';
      $Output .= $this->ShowLoginForm();
    } else {
      $Output .= $this->ShowLoginForm();
    }
    if(Core::Cast($this->System)->IsAdmin()) $Output .= '<div>Jsi přihlášen jako správce. <a href="?logoff">Odhlásit</a></div>';
    return $Output;
  }

  function ShowLoginForm(): string
  {
    return '<form method="post" action="?login">'.
      'Heslo: <input type="password" name="password" value=""/><br/>'.
      '<input type="submit" value="Přihlásit"/>'.
      '</form>';
  }
}

$Revision = 63; // Subversion revision
$DatabaseRevision = 51; // SQL structure revision
$ReleaseTime = strtotime('2021-08-03');

$Application = new Core();
$Application->ModuleManager->LoadModulesFromDir(dirname(__FILE__).'/Modules');
$Application->Modules = $Application->ModuleManager->Modules;
$Application->ModuleManager->InstallAll();
$Application->ModuleManager->StartAll();
$Application->RegisterPage([''], 'PageDanceList');
$Application->RegisterPage(['robots.txt'], 'PageRobots');
$Application->RegisterPage(['sitemap.xml'], 'PageSiteMap');
$Application->RegisterPage(['admin'], 'PageLogin');
$Application->Run();
