<?php

/* @var $System System */
$System = NULL;
/* @var $Database Database */
$Database = NULL;

include_once(dirname(__FILE__).'/../Packages/Package.php');
include_once(dirname(__FILE__).'/../Packages/Common/Common.php');
include_once(dirname(__FILE__).'/Form/Form.php');
include_once(dirname(__FILE__).'/VCL/General.php');
include_once(dirname(__FILE__).'/VCL/Database.php');

//define('NEW_PERMISSION', '1');

$MonthNames = array('', 'Leden', 'Únor', 'Březen', 'Duben', 'Květen', 'Červen',
  'Červenec', 'Srpen', 'Září', 'Říjen', 'Listopad', 'Prosinec');

$UnitNames = array('B', 'kB', 'MB', 'GB', 'TB', 'PB', 'EB');
$YesNo = array(false => 'Ne', true => 'Ano');

function HumanSize(int $Value): string
{
  global $UnitNames;

  $UnitIndex = 0;
  while ($Value > 1024)
  {
    $Value = round($Value / 1024, 3);
    $UnitIndex++;
  }
  return $Value.' '.$UnitNames[$UnitIndex];
}

function GetMicrotime(): float
{
  list($Usec, $Sec) = explode(' ', microtime());
  return (float)$Usec + (float)$Sec;
}

function ShowArray(array $Array): void
{
  echo('<pre style="font-size: 8pt;">');
  print_r($Array);
  echo('</pre>');
}

function HumanDate(?string $Time): string
{
  if ($Time != '')
  {
    $Date = explode(' ', $Time);
    $Parts = explode('-', $Date[0]);
    if ($Date != '0000-00-00') return ($Parts[2] * 1).'.'.($Parts[1] * 1).'.'.$Parts[0];
    else return '&nbsp;';
  } else return '&nbsp;';
}

// Show page listing numbers
function PagesList(string $URL, int $Page, int $TotalCount, int $CountPerPage): string
{
  $Count = ceil($TotalCount / $CountPerPage);
  $Around = 10;
  $Result = '';
  if ($Count > 1)
  {
    if ($Page > 0)
    {
      $Result.= '<a href="'.$URL.'0">&lt;&lt;</a> ';
      $Result.= '<a href="'.$URL.($Page - 1).'">&lt;</a> ';
    }
    $PagesMax = $Count - 1;
    $PagesMin = 0;
    if ($PagesMax > ($Page + $Around)) $PagesMax = $Page + $Around;
    if ($PagesMin < ($Page - $Around))
    {
      $Result.= ' .. ';
      $PagesMin = $Page - $Around;
    }
    for ($i = $PagesMin; $i <= $PagesMax; $i++)
    {
      if ($i == $Page) $Result.= '<strong>';
      $Result .= '<a href="'.$URL.$i.'">'.($i + 1).'</a> ';
      if ($i == $Page) $Result.= '</strong>';
    }
    if ($PagesMax < ($Count - 1)) $Result .= ' .. ';
    if ($Page < ($Count - 1))
    {
      $Result .= '<a href="'.$URL.($Page + 1).'">&gt;</a> ';
      $Result .= '<a href="'.$URL.($Count - 1).'">&gt;&gt;</a>';
    }
  }
  return $Result;
}

function ExtractTime($Time): array
{
  return array(
    'Year' => date('Y', $Time),
    'Month' => date('n', $Time),
    'Day' => date('j', $Time),
    'Hour' => date('h', $Time),
    'Minute' => date('i', $Time),
    'Second' => date('s', $Time)
  );
}

function GetQueryStringArray(string $QueryString): array
{
  $Result = array();
  $Parts = explode('&', $QueryString);
  foreach ($Parts as $Part)
  {
    if ($Part != '')
    {
      if (!strpos($Part, '=')) $Part .= '=';
      $Item = explode('=', $Part);
      $Result[$Item[0]] = $Item[1];
    }
  }
  return $Result;
}

function SetQueryStringArray(array $QueryStringArray): string
{
  $Parts = array();
  foreach ($QueryStringArray as $Index => $Item)
  {
    $Parts[] = $Index.'='.$Item;
  }
  return implode('&amp;', $Parts);
}

function GetPageList(string $ObjectName, int $TotalCount): array
{
  global $System;

  $QueryItems = GetQueryStringArray($_SERVER['QUERY_STRING']);

  $Result = '';
  if (array_key_exists('all', $QueryItems))
  {
    $PageCount = 1;
    $ItemPerPage = $TotalCount;
  } else
  {
    $ItemPerPage = $System->Config['Web']['ItemsPerPage'];
    $Around = round($System->Config['Web']['VisiblePagingItems'] / 2);
    $PageCount = floor($TotalCount / $ItemPerPage) + 1;
  }

  if (!array_key_exists($ObjectName.'Page', $_SESSION)) $_SESSION[$ObjectName.'Page'] = 0;
  if (array_key_exists('ObjectName', $_GET) and ($_GET['ObjectName'] == $ObjectName)) {
    if (array_key_exists('page', $_GET)) $_SESSION[$ObjectName.'Page'] = $_GET['page'] * 1;
  }
  if ($_SESSION[$ObjectName.'Page'] < 0) $_SESSION[$ObjectName.'Page'] = 0;
  if ($_SESSION[$ObjectName.'Page'] >= $PageCount) $_SESSION[$ObjectName.'Page'] = $PageCount - 1;
  $CurrentPage = $_SESSION[$ObjectName.'Page'];

  $Result .= 'Počet položek: <strong>'.$TotalCount.'</strong> &nbsp; Stránky: ';
  $QueryItems['ObjectName'] = $ObjectName;

  $Result = '';
  if ($PageCount > 1)
  {
    if ($CurrentPage > 0)
    {
      $QueryItems['page'] = 0;
      $Result.= '<a href="?'.SetQueryStringArray($QueryItems).'">&lt;&lt;</a> ';
      $QueryItems['page'] = ($CurrentPage - 1);
      $Result.= '<a href="?'.SetQueryStringArray($QueryItems).'">&lt;</a> ';
    }
    $PagesMax = $PageCount - 1;
    $PagesMin = 0;
    if ($PagesMax > ($CurrentPage + $Around)) $PagesMax = $CurrentPage + $Around;
    if ($PagesMin < ($CurrentPage - $Around))
    {
      $Result.= ' ... ';
      $PagesMin = $CurrentPage - $Around;
    }
    for ($i = $PagesMin; $i <= $PagesMax; $i++)
    {
      if ($i == $CurrentPage) $Result.= '<strong>'.($i + 1).'</strong> ';
      else {
       $QueryItems['page'] = $i;
       $Result .= '<a href="?'.SetQueryStringArray($QueryItems).'">'.($i + 1).'</a> ';
      }
    }
    if ($PagesMax < ($PageCount - 1)) $Result .= ' ... ';
    if ($CurrentPage < ($PageCount - 1))
    {
      $QueryItems['page'] = ($CurrentPage + 1);
      $Result.= '<a href="?'.SetQueryStringArray($QueryItems).'">&gt;</a> ';
      $QueryItems['page'] = ($PageCount - 1);
      $Result.= '<a href="?'.SetQueryStringArray($QueryItems).'">&gt;&gt;</a>';
    }
  }
  $QueryItems['all'] = '1';
  if ($PageCount > 1) $Result.= ' <a href="?'.SetQueryStringArray($QueryItems).'">Vše</a>';

  $Result = '<div style="text-align: center">'.$Result.'</div>';
  return array('SQLLimit' => ' LIMIT '.$CurrentPage * $ItemPerPage.', '.$ItemPerPage,
    'Page' => $CurrentPage,
    'Output' => $Result,
  );
}

$OrderDirSQL = array('ASC', 'DESC');
$OrderArrowImage = array('sort_asc.png', 'sort_desc.png');

function GetOrderTableHeader(string $ObjectName, array $Columns, string $DefaultColumn, int $DefaultOrder = 0): array
{
  global $OrderDirSQL, $OrderArrowImage, $Config, $System;

  if (array_key_exists('ObjectName', $_GET) and ($_GET['ObjectName'] == $ObjectName))
  {
    if (array_key_exists('OrderCol', $_GET)) $_SESSION[$ObjectName.'OrderCol'] = $_GET['OrderCol'];
    if (array_key_exists('OrderDir', $_GET)) $_SESSION[$ObjectName.'OrderDir'] = $_GET['OrderDir'];
  }
  if (!array_key_exists($ObjectName.'OrderCol', $_SESSION)) $_SESSION[$ObjectName.'OrderCol'] = $DefaultColumn;
  if (!array_key_exists($ObjectName.'OrderDir', $_SESSION) ) $_SESSION[$ObjectName.'OrderDir'] = $DefaultOrder;

  // Check OrderCol
  $Found = false;
  foreach ($Columns as $Column)
  {
    if ($Column['Name'] == $_SESSION[$ObjectName.'OrderCol'])
    {
      $Found = true;
      break;
    }
  }
  if (($_SESSION[$ObjectName.'OrderCol'] == '') or ($Found == false))
  {
    $_SESSION[$ObjectName.'OrderCol'] = $DefaultColumn;
    $_SESSION[$ObjectName.'OrderDir'] = $DefaultOrder;
  }
  // Check OrderDir
  if (($_SESSION[$ObjectName.'OrderDir'] != 0) and ($_SESSION[$ObjectName.'OrderDir'] != 1))
    $_SESSION[$ObjectName.'OrderDir'] = 0;

  $Result = '';
  $QueryItems = GetQueryStringArray($_SERVER['QUERY_STRING']);
  foreach ($Columns as $Index => $Column)
  {
    $QueryItems['ObjectName'] = $ObjectName;
    $QueryItems['OrderCol'] = $Column['Name'];
    $QueryItems['OrderDir'] = 1 - $_SESSION[$ObjectName.'OrderDir'];
    if ($Column['Name'] == $_SESSION[$ObjectName.'OrderCol'])
      $ArrowImage = '<img style="vertical-align: middle; border: 0px;" src="'.
      $System->Link('/images/'.$OrderArrowImage[$_SESSION[$ObjectName.'OrderDir']]).'" alt="order arrow">';
      else $ArrowImage = '';
    if ($Column['Name'] == '') $Result .= '<th>'.$Column['Title'].'</th>';
      else $Result .= '<th><a href="?'.SetQueryStringArray($QueryItems).'">'.$Column['Title'].$ArrowImage.'</a></th>';
  }
  return array(
    'SQL' => ' ORDER BY `'.$_SESSION[$ObjectName.'OrderCol'].'` '.$OrderDirSQL[$_SESSION[$ObjectName.'OrderDir']],
    'Output' => '<tr>'.$Result.'</tr>',
    'Column' => $_SESSION[$ObjectName.'OrderCol'],
    'Direction' => $_SESSION[$ObjectName.'OrderDir'],
  );
}

function GetRemoteAddress(): string
{
  if (array_key_exists('REMOTE_ADDR', $_SERVER)) $IP = $_SERVER['REMOTE_ADDR'];
  else $IP = '0.0.0.0';
  return $IP;
}

function IsInternetAddr(): bool
{
  global $Config;

  $Result = true;
  $RemoteAddr = GetRemoteAddress();
  foreach ($Config['Web']['IntranetSubnets'] as $Subnet)
  {
    if (substr($RemoteAddr, 0, strlen($Subnet)) == $Subnet)
    {
      $Result = false;
      break;
    }
  }
  return $Result;
}

function GetMemberByIP(Database $Database, string $IP): string
{
  $DbResult = $Database->query('SELECT `Id` FROM `Member` WHERE '.
  '(SELECT `Member` FROM `NetworkDevice` WHERE (SELECT `Device` FROM `NetworkInterface` '.
  'WHERE `LocalIP` = "'.$IP.'") = `NetworkDevice`.`Id`) = `Member`.`Id`');
  if ($DbResult->num_rows > 0)
  {
    $DbRow = $DbResult->fetch_assoc();
    return $DbRow['Id'];
  } else return '';
}

function CommandExist(string $Command): bool
{
  $Result = shell_exec('which '.$Command);
  return !empty($Result);
}

function RemoveDiacritic(string $Text): string
{
  return str_replace(
    array('á', 'č', 'ď', 'é', 'ě', 'í', 'ľ', 'ň', 'ó', 'ř', 'š', 'ť', 'ú', 'ů',
      'ý', 'ž', 'Á', 'Č', 'Ď', 'É', 'Ě', 'Í', 'Ľ', 'Ň', 'Ó', 'Ř', 'Š', 'Ť', 'Ú', 'Ů', 'Ý', 'Ž'),
    array('a', 'c', 'd', 'e', 'e', 'i', 'l', 'n', 'o', 'r', 's', 't', 'u', 'u',
      'y', 'z', 'A', 'C', 'D', 'E', 'E', 'I', 'L', 'N', 'O', 'R', 'S', 'T', 'U', 'U', 'Y', 'Z'),
    $Text);
}

function RouterOSIdent(string $Name): string
{
  return strtr(strtolower(trim($Name)), array(' ' => '-', '.' => '', '(' => '-', ')' => '-', ',' => '-',
  'č' => 'c', 'š' => 's', 'ě' => 'e', 'ř' => 'r', 'ž' => 'z', 'ý' => 'y',
  'á' => 'a', 'í' => 'i', 'é' => 'e', 'ů' => 'u', 'ú' => 'u', 'ď' => 'd',
  'ť' => 't', 'ň' => 'n', 'ó' => 'o',
  'Č' => 'c', 'Š' => 's', 'Ě' => 'e', 'Ř' => 'r', 'Ž' => 'z', 'Ý' => 'y',
  'Á' => 'a', 'Í' => 'i', 'É' => 'e', 'Ů' => 'u', 'Ú' => 'u', 'Ď' => 'd',
  'Ť' => 't', 'Ň' => 'n', 'Ó' => 'o',
  ));
}

function NotBlank(string $Text): string
{
  if ($Text == '') return '&nbsp;';
    else return $Text;
}

function strip_cdata(string $string): string
{
  preg_match_all('/<!\[cdata\[(.*?)\]\]>/is', $string, $matches);
  return str_replace($matches[0], $matches[1], $string);
}

function html2txt($document)
{
  $search = array('@<script[^>]*?>.*?</script>@si',  // Strip out javascript
               '@<[\/\!]*?[^<>]*?>@si',            // Strip out HTML tags
               '@<style[^>]*?>.*?</style>@siU',    // Strip style tags properly
               '@<![\s\S]*?--[ \t\n\r]*>@'         // Strip multi-line comments including CDATA
  );
  $text = preg_replace($search, '', $document);
  return $text;
}

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 RepeatFunction(int $Period, callable $Callback): void
{
  while (1)
  {
    $StartTime = time();
    call_user_func($Callback);
    $EndTime = time();
    $Delay = $Period - ($EndTime - $StartTime);
    if ($Delay < 0) $Delay = 0;

    echo('Waiting remaining '.$Delay.' of '.$Period.' seconds period...'."\n");
    sleep($Delay);
  }
}

function pack_array($v, $a)
{
  return call_user_func_array('pack', array_merge(array($v), (array)$a));
}

function file_get_contents_curl(string $Url)
{
  $Ch = curl_init();

  curl_setopt($Ch, CURLOPT_AUTOREFERER, TRUE);
  curl_setopt($Ch, CURLOPT_HEADER, 0);
  curl_setopt($Ch, CURLOPT_RETURNTRANSFER, 1);
  curl_setopt($Ch, CURLOPT_URL, $Url);
  curl_setopt($Ch, CURLOPT_FOLLOWLOCATION, TRUE);

  $Data = curl_exec($Ch);
  curl_close($Ch);
  return $Data;
}

function ExecuteNoError(callable $Function): void
{
  try
  {
    $LastErrorReporting = error_reporting();
    error_reporting(0);
    $Function();
  }
  finally
  {
    error_reporting($LastErrorReporting);
  }
}
