<?php

class PageNetworkTopology extends Page
{
  public string $TopHostName = 'NIX-ROUTER';

  function __construct(System $System)
  {
    parent::__construct($System);
    $this->Title = 'Topologie sítě';
    $this->Description = 'Grafické zobrazení topologie sítě';
    $this->ParentClass = 'PagePortal';
  }

  function Show(): string
  {
    if (count($this->System->PathItems) > 1)
    {
      if ($this->System->PathItems[1] == 'topologie.png') return $this->ShowImage();
        else return PAGE_NOT_FOUND;

    } else return $this->ShowOverview();
  }

  function ShowImage(): string
  {
    $this->RawPage = true;
    Core::Cast($this->System)->BaseView->FormatHTML = false;

    if (array_key_exists('debug', $_GET)) $debug = $_GET['debug'];
      else $debug = 0;

    // Vytvoř stromy a ulož výsledek do databáze
    $DbResult = $this->Database->query("SELECT MAX(Pos), MAX(Depth) FROM NetworkTopology");
    $item = $DbResult->fetch_array();
    $width = $item[0];
    $height = $item[1];

    $spacex = 32;
    $spacey = 68;
    $halfx = $spacex / 2;
    $halfy = $spacey / 2;
    // Načtení pomocných obrázků
    $im_comp = imagecreatefrompng(dirname(__FILE__).'/images/comp.png');
    $im_dev = imagecreatefrompng(dirname(__FILE__).'/images/device.png');
    // Generování obrázku
    $im = imagecreate(($width + 1.6) * $spacex, ($height + 1) * $spacey);
    $background_color = imagecolorallocate($im, 255, 255, 255);
    $black = imagecolorallocate($im, 0, 0, 0);
    $red = imagecolorallocate($im, 255, 0, 0);
    $green = imagecolorallocate($im, 0, 128, 0);
    $blue = imagecolorallocate($im, 100, 100, 255);
    $gray = imagecolorallocate($im, 160, 160, 160);

    //$DbResult = $Database->query("SELECT * FROM hosts, NetworkTopology WHERE host = id AND used=1");
    $DbResult = $this->Database->query('SELECT NetworkTopology.*, NetworkTopology.Host AS Id, '.
      'NetworkDevice.Name AS Name, '.
      'NetworkDevice.Online AS Online, NetworkDeviceType.IconName AS IconName, 1 AS ShowOnline '.
      'FROM NetworkTopology LEFT JOIN NetworkDevice ON NetworkDevice.Id = NetworkTopology.Host '.
      'LEFT JOIN NetworkDeviceType ON NetworkDevice.Type = NetworkDeviceType.Id');
    while ($item = $DbResult->fetch_array())
    {
      $id = $item['Id'];
      $vleft = $item['Pos'];
      $vtop = $item['Depth'];
      $vfirst = $item['First'];
      $vlast = $item['Last'];
      $xpos = $vleft * $spacex;
      if (($vtop > 0) or ($item['Name'] == $this->TopHostName))
      {
        if ($vtop > 0) imageline($im, $xpos + $halfx, $vtop * $spacey, $xpos + $halfx, $vtop * $spacey + 8, $black);
        if ($vfirst >= 0)
        {
          imageline($im, $vfirst*$spacex + $halfx, $vtop * $spacey + $spacey, $vlast*$spacex + $halfx, $vtop * $spacey + $spacey, $black);
          imageline($im, $xpos + $halfx, ($vtop + 1) * $spacey - 10, $xpos + $halfx, ($vtop + 1) * $spacey, $black);
        }
        //    $ip = explode('.',$item['IP']);
        //    if (!array_key_exists(3, $ip)) $ip[3] = '';
        if ($item['IconName'] == 'comp')
        {
          if ($item['Online'] == 1) $color = $green;
          else $color = $black;
          $image = $im_comp;
        } else $image = $im_dev;
        if ($item['IconName'] == 'device')
        {
          if ($item['Online'] == 1) $color = $green;
          else $color = $red;
          $image = $im_dev;
        }
        if ($item['ShowOnline'] == 0)
        {
          $color = $gray;
          $image = $im_dev;
        }
        //      $text='IP: '.$ip[0];
        //      imagestring($im,2,xpos($id)+($spacex-strlen($text)*imagefontwidth(2))/2,$vtop[$id]*$spacey+24+imagefontheight(2),$text,$black);
        imagecopy($im, $image, $xpos+$halfx-15, $vtop*$spacey+12, 0, 0, 30, 30);
        //    imagerectangle($im,xpos($id)+$halfx-6,$vtop[$id]*$spacey+16,xpos($id)+$halfx+6,$vtop[$id]*$spacey+28,$color);
        if ($debug) {
          imagestring($im, 2, $xpos+($spacex-strlen($item['Id'])*imagefontwidth(2))/2, $vtop*$spacey+31+imagefontheight(2), $item['Id'], $color);
        } else imagestring($im,2,$xpos+($spacex-strlen($item['Name'])*imagefontwidth(2))/2, $vtop*$spacey+31+imagefontheight(2), $item['Name'], $color);
      }
    }

    // === Sestavení výsledného souboru ============================================
    if ($debug == 0)
    {
      Header("Content-type: image/png");
      Header("Cache-Control: no-cache");  // Dynamický graf, nekešovat
      imagepng($im);
      imagedestroy($im);
      imagedestroy($im_comp);
      imagedestroy($im_dev);
    }
    return '';
  }

  function ShowOverview(): string
  {
    $Output = '<img src="topologie.png"><br/>
<p>Vysvětlivky: Obrázek znázorňuje připojení prvků sítě do internetu.<br/>
<img src="Modules/NetworkTopology/images/comp.png"> Je počítač zapojený v síti a pod ním je uvedeno jeho jméno.
<span style="color:green">Zelená barva</span> znamená, že počitač je zapnutý a
online. Černá barva znamená, že počítač je vypnutý, nebo není online.<br/>
<img src="Modules/NetworkTopology/images/device.png"> Představuje komunikační zařízení připojené do sítě, které
mají běžet nepřetržitě. Pokud je zařízení online, je text pod ním zobrazen
<span style="color:green">zelenou barvou</span>, pokud není online, je zobrazen
<span style="color:red">červenou barvou</span>. Dostupnost prvků je kontrolována
z počítače Centrála, takže při výpadku zařízení nebude možné zjistit stav
zařízení, které jsou přes něj připojeny. U zařízení, kde není stav možné
zjišťovat je použita <span style="color:gray">šedá barvou</span>.</p>';
    return $Output;
  }
}

class ModuleNetworkTopology extends Module
{
  function __construct(System $System)
  {
    parent::__construct($System);
    $this->Name = 'NetworkTopology';
    $this->Version = '1.0';
    $this->Creator = 'Chronos';
    $this->License = 'GNU/GPLv3';
    $this->Description = 'Generate image of network device interconnection';
    $this->Dependencies = array(ModuleNetwork::GetName());
    $this->Models = array(NetworkTopology::GetClassName());
  }

  function DoStart(): void
  {
    $this->System->RegisterPage(['topologie'], 'PageNetworkTopology');
  }
}

class NetworkTopology extends Model
{
  static function GetModelDesc(): ModelDesc
  {
    $Desc = new ModelDesc(self::GetClassName());
    $Desc->AddInteger('Host');
    $Desc->AddInteger('Depth');
    $Desc->AddInteger('Pos');
    $Desc->AddInteger('First');
    $Desc->AddInteger('Last');
    return $Desc;
  }
}
