<?php

include('global.php');

class NetworkHostTopology
{
  var $Tree;
  var $TopHostId;
  var $HostWidth = 64;
  var $HostHeight = 64;
  var $Image;
  var $LineColor;
  var $BackgroundColor;
  var $TextColor;
  var $ImageDevice;
  var $ImageComputer;
  var $RelPos;
  var $Levels = array();

  function NetworkHostTopology($TopHostId)
  {
    $this->Tree = array();
    $this->TopHostId = $TopHostId;
  }

  function LoadTree()
  {
    global $Database;

    $Parent = 38;
    $Hosts = array();
    $DbResult = $Database->select('hosts', 'id, name, ip, parent, online', 'used=1');
    while($DbRow = $DbResult->fetch_array())
    {
      if(!array_key_exists($DbRow['id'], $Hosts)) $Hosts[$DbRow['id']] = array('subitems' => array());
      $Hosts[$DbRow['id']] = array('id' => $DbRow['id'], 'name' => $DbRow['name'], 'parent' => $DbRow['parent'], 'online' => $DbRow['online'], 'subitems' => $Hosts[$DbRow['id']]['subitems']);
      if(!array_key_exists($DbRow['parent'], $Hosts)) $Hosts[$DbRow['parent']] = array('subitems' => array());
      $Hosts[$DbRow['parent']]['subitems'][] = &$Hosts[$DbRow['id']];
      $Hosts[$DbRow['id']]['parent_node'] = &$Hosts[$DbRow['parent']];
    }

    $this->Tree = $Hosts[$this->TopHostId]; 
  }
  
  function CalculateDimension(&$Host)
  {
    $Result = array('min' => $Host['displacement'], 'max' => $Host['displacement']);
    foreach($Host['subitems'] as $Index => $SubHost)
    {
      $SubitemResult = $this->CalculateDimension($Host['subitems'][$Index]);
      $Result['min'] = min($SubitemResult['min'], $Result['min']);
      $Result['max'] = max($SubitemResult['max'], $Result['max']);
    }
    return($Result);
  }

  function CalculateDisplacement(&$Host, $Level = 0)
  {
    if(!array_key_exists('displacement', $Host)) $Host['displacement'] = 0;
    $Host['level'] = $Level;
    foreach($Host['subitems'] as $Index => $SubHost)
    {
      $Host['subitems'][$Index]['rel_displacement'] = (-(count($Host['subitems']) - 1) * 0.5 + $Index) * $this->HostWidth;
      $Host['subitems'][$Index]['displacement'] = $Host['displacement'] + $Host['subitems'][$Index]['rel_displacement'];
      $this->CalculateDisplacement($Host['subitems'][$Index], $Level + 1);
    }
  }

  function MoveNode(&$Host, $Displacement)
  { 
    $Host['displacement'] = $Host['displacement'] + $Displacement;
    foreach($Host['subitems'] as $Index => $SubHost)
    {
      $this->MoveNode($Host['subitems'][$Index], $Displacement);
    }
  }

  function CheckColision()
  {
    foreach($this->Levels as $Index => $Level)
    {
      for($I = 0; $I < count($Level) - 1; $I++)
        if($Level[$I]['displacement'] >= $Level[$I + 1]['displacement'])
        {
          // Search for common parent
          $LeftHost = $Level[$I];
          $RightHost = $Level[$I + 1];
          while(($LeftHost['level'] > 0) and ($LeftHost['parent'] != $RightHost['parent']))
          {
            $LeftHost = $LeftHost['parent_node'];
            $RightHost = $RightHost['parent_node'];
          }
          $Host = $RightHost['parent_node']['subitems'][0];
          $II = 0;
          while($RightHost['parent_node']['subitems'][$II]['id'] != $RightHost['id']) $II++;
          while($II < count($RightHost['parent_node']['subitems'])) 
          {
            $this->MoveNode($RightHost['parent_node']['subitems'][$II], $Level[$I]['displacement'] - $Level[$I + 1]['displacement']);
            $II++;
          }
        }
    }
  }
  
  function BuildLevels(&$Host)
  {
    $this->Levels[$Host['level']][] = &$Host;
    foreach($Host['subitems'] as $Index => $SubHost)
    {
      $this->BuildLevels($Host['subitems'][$Index]);
    }
  }

  function DrawNode(&$Host)
  {
    $ParentHostPos = array('x' => -$this->RelPos['min'] + $Host['displacement'], 'y' => $Host['level'] * $this->HostHeight);
    foreach($Host['subitems'] as $Index => $SubHost)
    {
      $HostPos = array('x' => -$this->RelPos['min'] + $SubHost['displacement'], 'y' => $SubHost['level'] * $this->HostHeight);
      imageline($this->Image, $ParentHostPos['x'], $ParentHostPos['y'], $ParentHostPos['x'], $ParentHostPos['y'] + $this->HostHeight * 0.5,   $this->LineColor); 
      imageline($this->Image, $ParentHostPos['x'], $ParentHostPos['y'] + $this->HostHeight * 0.5, $HostPos['x'], $ParentHostPos['y']  + $this->HostHeight * 0.5, $this->LineColor); 
      imageline($this->Image, $HostPos['x'], $ParentHostPos['y'] + $this->HostHeight * 0.5, $HostPos['x'], $HostPos['y'], $this->LineColor); 
      $this->DrawNode(&$Host['subitems'][$Index]);
      imagecopy($this->Image, $this->ImageComputer, $HostPos['x'] - imagesx($this->ImageComputer) * 0.5, $HostPos['y'] - imagesy($this->ImageComputer) * 0.5, 0, 0, 30, 30);
      imagestring($this->Image, 2, $HostPos['x'] - (strlen($SubHost['name']) * imagefontwidth(2)) / 2, $HostPos['y'] + imagesy($this->ImageComputer) * 0.5, $SubHost['name'], $this->TextColor);
    }
  }

  function ProduceImage()
  {
    $this->CalculateDisplacement($this->Tree);
    $this->BuildLevels($this->Tree);
    $this->CheckColision();
    $this->RelPos = $this->CalculateDimension($this->Tree);
    $this->ImageComputer = imagecreatefrompng('is/images/comp.png');
    $this->ImageDevice = imagecreatefrompng('is/images/device.png');

    header("Content-type: image/png");
    header("Cache-Control: no-cache");
    $this->Image = imagecreate($this->RelPos['max'] - $this->RelPos['min'], count($this->Levels) * $this->HostHeight);
    $this->BackgroundColor = imagecolorallocate($this->Image, 255, 255, 255);  // Black
    $this->LineColor = imagecolorallocate($this->Image, 0, 200, 0);  // Black
    $this->TextColor = imagecolorallocate($this->Image, 0, 0, 0);  // Black
    $this->DrawNode($this->Tree);
    imageline($this->Image, 0, 0, 0, 0, $this->BackgroundColor);
    imagepng($this->Image);
    imagedestroy($this->Image);
  }
}

$Topology = new NetworkHostTopology(38);
$Topology->LoadTree();
//print_r($Topology->Tree);
$Topology->ProduceImage();

?>