<?php

class ModuleWiki extends Module
{
  function __construct(System $System)
  {
    parent::__construct($System);
    $this->Name = 'Wiki';
    $this->Version = '1.0';
    $this->Creator = 'Chronos';
    $this->License = 'GNU/GPLv3';
    $this->Description = 'Mediawiki style page management';
    $this->Dependencies = array(ModuleUser::GetName());
    $this->Models = array(WikiPage::GetClassName(), WikiPageContent::GetClassName());
  }

  function DoStart(): void
  {
    $this->LoadPages();
  }

  function LoadPages(): void
  {
    $DbResult = $this->Database->select('WikiPage', '*', 'VisibleInMenu=1');
    while ($DbRow = $DbResult->fetch_assoc())
    {
      Core::Cast($this->System)->RegisterPage([$DbRow['NormalizedName']], 'PageWiki');
      Core::Cast($this->System)->RegisterMenuItem(array(
        'Title' => $DbRow['Name'],
        'Hint' => '',
        'Link' => Core::Cast($this->System)->Link('/'.$DbRow['NormalizedName'].'/'),
        'Permission' => LICENCE_ANONYMOUS,
        'Icon' => '',
      ), 2);
    }
  }
}

class WikiPage extends Model
{
  static function GetModelDesc(): ModelDesc
  {
    $Desc = new ModelDesc(self::GetClassName());
    $Desc->AddString('Name');
    $Desc->AddString('NormalizedName');
    $Desc->AddBoolean('VisibleInMenu');
    return $Desc;
  }
}

class WikiPageContent extends Model
{
  static function GetModelDesc(): ModelDesc
  {
    $Desc = new ModelDesc(self::GetClassName());
    $Desc->AddReference('Page', WikiPage::GetClassName());
    $Desc->AddDateTime('Time');
    $Desc->AddText('Content');
    $Desc->AddReference('User', User::GetClassName());
    return $Desc;
  }
}

class PageWiki extends Page
{
  function __construct(System $System)
  {
    parent::__construct($System);
    $this->Title = 'Wiki';
    $this->Description = 'Wiki stránky';
    $this->ParentClass = 'PagePortal';
  }

  function Show(): string
  {
    if (array_key_exists('Action', $_GET))
    {
      if ($_GET['Action'] == 'Edit') $Output = $this->EditContent();
      else if ($_GET['Action'] == 'EditSave') $Output = $this->SaveContent();
      else if ($_GET['Action'] == 'History') $Output = $this->ShowHistory();
      else $Output = $this->ShowContent();
    } else $Output = $this->ShowContent();
    return $Output;
  }

  function ShowContent(): string
  {
    $PageName = $this->System->PathItems[count($this->System->PathItems) - 1];
    $DbResult = $this->Database->select('WikiPage', 'Name, Id', 'NormalizedName="'.$PageName.'"');
    if ($DbResult->num_rows > 0)
    {
      $DbRow = $DbResult->fetch_assoc();
      if (array_key_exists('ver', $_GET))
      {
        $DbResult2 = $this->Database->select('WikiPageContent', '*', 'Page='.$DbRow['Id'].' AND Id='.$_GET['ver']*1);
        if ($DbResult2->num_rows > 0)
        {
          $DbRow2 = $DbResult2->fetch_assoc();
          $Output = '<h3>Archív stránky '.$DbRow['Name'].' ('.HumanDateTime($DbRow2['Time']).')</h3>';
          $Output .= $DbRow2['Content'];
          if (ModuleUser::Cast($this->System->GetModule('User'))->User->Licence(LICENCE_MODERATOR))
            $Output .= '<div><a href="?Action=Edit">Upravit nejnovější</a> <a href="?Action=History">Historie</a></div>';
        } else $Output = ShowmMessage('Wiki stránka nenalezena', MESSAGE_CRITICAL);
      } else
      {
        $DbResult2 = $this->Database->select('WikiPageContent', '*', 'Page='.$DbRow['Id'].' ORDER BY Time DESC LIMIT 1');
        if ($DbResult2->num_rows > 0)
        {
          $DbRow2 = $DbResult2->fetch_assoc();
          $Output = '<h3>'.$DbRow['Name'].'</h3>';
          $Output .= $DbRow2['Content'];
          if (ModuleUser::Cast($this->System->GetModule('User'))->User->Licence(LICENCE_MODERATOR))
            $Output .= '<div><a href="?Action=Edit">Upravit</a> <a href="?Action=History">Historie</a></div>';
        } else $Output = ShowMessage('Wiki stránka nenalezena', MESSAGE_CRITICAL);
      }
    } else $Output = ShowMessage('Wiki stránka nenalezena', MESSAGE_CRITICAL);
    return $Output;
  }

  function EditContent(): string
  {
    if (ModuleUser::Cast($this->System->GetModule('User'))->User->Licence(LICENCE_MODERATOR))
    {
    $PageName = $this->System->PathItems[count($this->System->PathItems) - 1];
    $DbResult = $this->Database->select('WikiPage', 'Name, Id', 'NormalizedName="'.$PageName.'"');
    if ($DbResult->num_rows > 0)
    {
      $DbRow = $DbResult->fetch_assoc();
      $Output = '<h3>Úprava '.$DbRow['Name'].'</h3>';
      $DbResult2 = $this->Database->select('WikiPageContent', '*', 'Page='.$DbRow['Id'].' ORDER BY Time DESC LIMIT 1');
      if ($DbResult2->num_rows > 0)
      {
        $DbRow2 = $DbResult2->fetch_assoc();
        $Output .= '<form action="?Action=EditSave" method="post">'.
        '<textarea name="content" rows="8" cols="80" onkeydown="ResizeTextArea(this)" class="textedit">'.$DbRow2['Content'].'</textarea><br/>'.
        '<input type="submit" name="save" value="Uložit"/> '.
        '<input type="button" name="cancel" value="Zrušit" onclick="location.href=\'?\'"/>'.
        '</form>';
      } else $Output = ShowMessage('Wiki stránka nenalezena', MESSAGE_CRITICAL);
    } else $Output = ShowMessage('Wiki stránka nenalezena', MESSAGE_CRITICAL);
    } else $Output = ShowMessage('Nemáte oprávnění', MESSAGE_CRITICAL);
    return $Output;
  }

  function SaveContent(): string
  {
    if (ModuleUser::Cast($this->System->GetModule('User'))->User->Licence(LICENCE_MODERATOR))
    {
    $PageName = $this->System->PathItems[count($this->System->PathItems) - 1];
    $DbResult = $this->Database->select('WikiPage', 'Name, Id', 'NormalizedName="'.$PageName.'"');
    if ($DbResult->num_rows > 0)
    {
      $DbRow = $DbResult->fetch_assoc();
      if (array_key_exists('content', $_POST) and array_key_exists('save', $_POST))
      {
        $this->Database->insert('WikiPageContent', array('Content' => stripslashes($_POST['content']),
          'User' => ModuleUser::Cast($this->System->GetModule('User'))->User->Id, 'Time' => 'NOW()', 'Page' => $DbRow['Id']));
        $Output = ShowMessage('Wiki stránka uložena', MESSAGE_INFORMATION);
      } else $Output = ShowMessage('Nezadána platná data', MESSAGE_CRITICAL);
      $Output .= $this->ShowContent();
    } else $Output = ShowMessage('Wiki stránka nenalezena', MESSAGE_CRITICAL);
    } else $Output = ShowMessage('Nemáte oprávnění', MESSAGE_CRITICAL);
    return $Output;
  }

  function ShowHistory(): string
  {
    if (ModuleUser::Cast($this->System->GetModule('User'))->User->Licence(LICENCE_MODERATOR))
    {
      $PageName = $this->System->PathItems[count($this->System->PathItems) - 1];
      $DbResult = $this->Database->select('WikiPage', 'Name, Id', 'NormalizedName="'.$PageName.'"');
      if ($DbResult->num_rows > 0)
      {
        $DbRow = $DbResult->fetch_assoc();

        $Output = '<h3>Historie stránky '.$DbRow['Name'].'</h3>';
        $DbResult2 = $this->Database->query('SELECT COUNT(*) FROM `WikiPageContent` WHERE Page='.$DbRow['Id']);
        $DbRow2 = $DbResult2->fetch_row();
        $PageList = GetPageList('WikiHistory', $DbRow2[0]);

        $Output .= $PageList['Output'];
        $Output .= '<table class="BaseTable">';

        $TableColumns = array(
            array('Name' => 'Time', 'Title' => 'Čas'),
            array('Name' => 'User', 'Title' => 'Uživatel'),
            array('Name' => 'Action', 'Title' => 'Akce'),
        );

        $Order = GetOrderTableHeader('WikiHistory', $TableColumns, 'Time', 1);
        $Output .= $Order['Output'];

        $DbResult2 = $this->Database->query('SELECT *, (SELECT `Name` FROM `User` WHERE `User`.`ID`=`WikiPageContent`.`User`) AS `UserName` '.
          ' FROM `WikiPageContent` WHERE Page='.
          $DbRow['Id'].' '.$Order['SQL'].$PageList['SQLLimit']);
        while ($PageContent = $DbResult2->fetch_assoc())
        {
          $Output .= '<tr>'.
            '<td>'.HumanDateTime($PageContent['Time']).'</td>'.
            '<td><a href="'.$this->System->Link('/user.php?user='.$PageContent['User']).'">'.$PageContent['UserName'].'</a></td>'.
            '<td><a href="?id='.$PageContent['Id'].'&amp;ver='.$PageContent['Id'].'">Zobrazit</a></td>';
          $Output .= '</tr>';
        }

        $Output .= '</table>'.
          $PageList['Output'];
      } else $Output = ShowMessage('Wiki stránka nenalezena', MESSAGE_CRITICAL);
    } else $Output = ShowMessage('Nemáte oprávnění', MESSAGE_CRITICAL);
    return $Output;
  }

  function ToHtml(string $text): string
  {
    $text = preg_replace('/&lt;source lang=&quot;(.*?)&quot;&gt;(.*?)&lt;\/source&gt;/', '<pre lang="$1">$2</pre>', $text);
    $text = preg_replace('/======(.*?)======/', '<h5>$1</h5>', $text);
    $text = preg_replace('/=====(.*?)=====/', '<h4>$1</h4>', $text);
    $text = preg_replace('/====(.*?)====/', '<h3>$1</h3>', $text);
    $text = preg_replace('/===(.*?)===/', '<h2>$1</h2>', $text);
    $text = preg_replace('/==(.*?)==/', '<h1>$1</h1>', $text);
    $text = preg_replace("/'''(.*?)'''/", '<strong>$1</strong>', $text);
    $text = preg_replace("/''(.*?)''/", '<em>$1</em>', $text);
    $text = preg_replace('/&lt;s&gt;(.*?)&lt;\/s&gt;/', '<strike>$1</strike>', $text);
    $text = preg_replace('/\[\[Image:(.*?)\|(.*?)\]\]/', '<img src="$1" alt="$2" title="$2" />', $text);
    $text = preg_replace('/\[(.*?) (.*?)\]/', '<a href="$1" title="$2">$2</a>', $text);
    $text = preg_replace('/&gt;(.*?)\n/', '<blockquote>$1</blockquote>', $text);

    $text = preg_replace('/\* (.*?)\n/', '<ul><li>$1</li></ul>', $text);
    $text = preg_replace('/<\/ul><ul>/', '', $text);

    $text = preg_replace('/# (.*?)\n/', '<ol><li>$1</li></ol>', $text);
    $text = preg_replace('/<\/ol><ol>/', '', $text);

    $text = str_replace("\r\n\r\n", '</p><p>', $text);
    $text = str_replace("\r\n", '<br/>', $text);
    $text = '<p>'.$text.'</p>';
    return $text;
  }
}
