<?php

class UpdateManager
{
  public int $Revision;
  public array $Trace;
  public string $VersionTable;
  public Database $Database;
  public string $InstallMethod;

  function __construct()
  {
    $this->Revision = 0;
    $this->Trace = array();
    $this->VersionTable = 'SystemVersion';
    $this->InstallMethod = 'FullInstall';
    $this->InsertSampleDataMethod = 'InsertSampleData';
  }

  function GetDbVersion(): ?int
  {
    $DbResult = $this->Database->select($this->VersionTable, '*', 'Id=1');
    $Version = $DbResult->fetch_assoc();
    return $Version['Revision'];
  }

  function IsInstalled(): bool
  {
    $DbResult = $this->Database->query('SHOW TABLES LIKE "'.$this->VersionTable.'"');
    return $DbResult->num_rows > 0;
  }

  function IsUpToDate(): bool
  {
    return $this->Revision <= $this->GetDbVersion();
  }

  function Upgrade(): string
  {
    $DbRevision = $this->GetDbVersion();
    $Output = 'Počáteční revize databáze: '.$DbRevision.'<br/>';
    while ($this->Revision > $DbRevision)
    {
      if (!array_key_exists($DbRevision, $this->Trace))
        die('Missing upgrade trace for revision '.$DbRevision);
      $TraceItem = $this->Trace[$DbRevision];
      $Output .= 'Aktualizace na verzi '.$TraceItem['Revision'].':<br/>';
      // Show applied SQL queries immediatelly
      echo($Output);
      $Output = '';
      $RevUpdate = $TraceItem['Function'];
      $RevUpdate($this);
      $DbRevision = $TraceItem['Revision'];
      $this->Database->query('UPDATE `'.$this->VersionTable.'` SET `Revision`= '.
        $TraceItem['Revision'].' WHERE `Id`=1');
    }
    return $Output;
  }

  function Install(): void
  {
    $InstallMethod = $this->InstallMethod;
    $InstallMethod($this);
  }

  function Uninstall(): void
  {
  }

  function InsertSampleData(): void
  {
    $InstallMethod = $this->InsertSampleDataMethod;
    $InstallMethod($this);
  }

  function Execute(string $Query): DatabaseResult
  {
    echo($Query.';<br/>');
    flush();
    return $this->Database->query($Query);
  }
}
