<?php 
# longtag needs a trailing [\s]

require_once ( 'jpgraph/jpgraph.php' ) ;
require_once ( 'jpgraph/jpgraph_canvas.php' ) ;
require_once ( 'jpgraph/jpgraph_line.php' ) ;
require_once ( 'jpgraph/jpgraph_date.php' ) ;

$PORT     = 22007 ;
$DEBUG    = 0 ;
$IMG_NP_W = 100 ;
$IMG_NP_H = 50 ;

function croak ( $txt, $W = 0, $H = 0 )
  { global $DEBUG ;
    if ( $DEBUG )
      { echo "$txt<BR>" ; exit ; }
    else
      { img_txt ( $txt, $W, $H ) ; }
  }

function maxx ( $a )
  { if ( reset ( $a ) ) { $r = current ( $a ) ; } ;
    foreach ( $a as $x )
      { if ( is_null ( $r ) )
          { $r = $x ; }
        elseif ( ! is_null ( $x ) and $x > $r )
          { $r = $x  ; }
      }
    return $r ;
  }

function minx ( $a )
  { if ( reset ( $a ) ) { $r = current ( $a ) ; } ;
    foreach ( $a as $x )
      { if ( is_null ( $r ) )
          { $r = $x ; }
        elseif ( ! is_null ( $x ) and $x < $r )
          { $r = $x  ; }
      }
    return $r ;
  }

function avgx ( $a )
  { $n = 0 ;
    $t = 0 ;
    foreach ( $a as $x )
      { if ( ! is_null ( $x ) )
          { $n ++ ; $t += $x  ; }
      }
    return $n ? $t / $n : null ;
  }

function curx ( $a )
  { if ( $cnt = count ( $a ) )
      { return $a [ $cnt - 1 ] ; }
    else
      { return null ; }
  }

function img_txt ( $txt, $W = 0, $H = 0 )
  { $lines = explode ( "\n", $txt ) ;
    $cnt  = count ( $lines ) ;
    $max  = maxx ( array_map ( "strlen", $lines ) ) ;
    if ( ! $W ) { $W = 15 + 6 * $max ; }
    if ( ! $H ) { $H = 15 * ( $cnt + 1 ) ; }
    $grap = new CanvasGraph ( $W, $H, 'auto' ) ;
    $grap -> SetMargin (5,5,5,5) ;
    $grap -> SetMarginColor ( "red" ) ;
    $grap -> InitFrame () ;
    $text = new Text ( $txt, 10, 10 ) ;
    $text -> SetColor ( 'blue' ) ;
    $text -> Align ( 'left', 'top' ) ;
    $text -> Stroke ( $grap -> img ) ;
    header ( "Content-type: image/png" ) ;
    $grap -> Stroke () ;
    exit ;
  }

# img_txt ( "aap noot mies\nwim zus jet\nblib blob" ) ; exit ;
# img_txt ( "aap noot mies wim zus jet blib blob" ) ; exit ;

function dmp ( $s, $t = 'tag' )
  { global $DEBUG ;
    if ( $DEBUG ) { printf ( "$t [%s]<BR>\n", $s ) ; }
  }

function fwrite_stream ($fp, $string)
  { for ( $res = 0 ; $res < strlen($string) ; $res += $fwrite)
      { $fwrite = fwrite ( $fp, substr($string, $res ) ) ;
        if ( $fwrite === false ) { return $res ; }
      }
    return $res ;
  }

function print_meta ( $fp )
  { global $DEBUG ;
    if ( $DEBUG )
      { $meta = stream_get_meta_data ( $fp ) ;
        print_r($meta) ;
        print "<br>\n" ;
      }
  }

function get_mesg ( $server, $port, $qwe )
  { dmp ( $qwe, 'QUERY_STRING' ) ;
    $fp = stream_socket_client ( "tcp://$server:$port", $errno, $errstr, 1 ) ;
    if ( $fp === FALSE ) { croak ( "can't talk to $server" ) ; }
    $write = fwrite_stream ( $fp, "$qwe\n" ) ;
    dmp ( "write [$write]<br>\n" ) ;
    if ( ! $write ) { croak ( "can't write to server" ) ; }
    stream_set_timeout ( $fp, 3 ) ;
    stream_socket_shutdown ( $fp, 1 ) ;
    print_meta ( $fp ) ;
    $mesg = array () ;
    $cnt = 0 ;
    while ( ! feof ( $fp ) )
      { $str = fgets ( $fp, 16 * 4096 ) ;
        $len = strlen ( $str ) ;
        dmp ( "cnt [$cnt] read[$len]" ) ;
        if ( $len )
          { $lst = count ( $mesg ) - 1 ;
            if ( $lst == -1 or substr ( $mesg [ $lst ], -1 ) == "\n" )
              { $mesg [] = $str ; }
            else
              { $mesg [ $lst ] .= $str ; }
          }
        print_meta ( $fp ) ;
        $cnt ++ ;
      }
    stream_socket_shutdown ( $fp, STREAM_SHUT_RDWR ) ;
    return $mesg ;
  }

function make_time ( $x, $t = 0 )
  { if ( $t == 0 ) { $t = time () ; }
    $vals = array
      ( 's' => date ( 's', $t )
      , 'm' => date ( 'i', $t )
      , 'h' => date ( 'G', $t )
      , 'D' => date ( 'j', $t )
      , 'M' => date ( 'n', $t )
      , 'Y' => date ( 'Y', $t )
      ) ;
    foreach ( $x as $key => $val ) { $vals [ $key ] = $val ; }
#   foreach ( $vals as $key => $val ) { echo "$key $val " ; }
#   printf ( "<= %s [%s]<br>\n", $t, date ( 'r', $t ) ) ;
    return mktime
      ( $vals [ "h" ]
      , $vals [ "m" ]
      , $vals [ "s" ]
      , $vals [ "M" ]
      , $vals [ "D" ]
      , $vals [ "Y" ]
      ) ;
  }

function first_of_month ( $t = 0 )
  { if ( $t == 0 ) { $t = time () ; }
    return make_time ( array ( 'h' => 12, 'D' => 1 ), $t ) ;
  }

function first_of_next ( $t, $m = 1 )
  { if ( $t == 0 ) { $t = time () ; }
    return make_time
      ( array ( 'h' => 12, 'D' => 1, 'M' => date ( 'n', $t ) + $m )
      , $t
      ) ;
  }

function gen_graph ( $cols, $rows, $host, $ival, $kind, $show )
  { global $DEBUG ;
    $nams  = implode ( ',', $cols ) ;
    $rcnt  = count ( $rows ) ;
    $W = 500 ;
    $H = 250 ;
#   croak ( "$host rows [$rcnt]", $W, $H ) ;
    if ( ! $rcnt ) { croak ( "$host: no rows", $W, $H ) ; }
    if ( ! $nams ) { croak ( "$host: no cols", $W, $H ) ; }
    $col = $cols [ 1 ] ;
    $xs  = array () ;
    $ys  = array () ;
    $us  = array () ;
    $all_null = 1 ;
    foreach ( $rows as $row )
      { $x = $row [ 0 ] ;
        $y = $row [ 1 ] ;
        if ( ! is_null ( $y ) )
          { $xs [] = $x ; $ys [] = $y ; $all_null = 0 ; }
      }
    if ( $all_null ) { croak ( "no valid data" ) ; }
    if ( $kind == 'gbs' )
      { foreach ( $ys as &$y ) { $y = $y / 1024 / 1024 ; } }
    elseif ( $kind == 'days' )
      { foreach ( $ys as &$y ) { $y = sprintf ( '%.3f', $y / 24 / 3600 ) ; } }
    elseif ( $kind == 'msec' )
      { foreach ( $ys as &$y ) { $y = 1000 * abs ( $y ) ; } }

    $grap = new Graph ( $W, $H ) ;
    $xmin = $xs [ 0 ] ;
    $xmax = $xs [ count ( $xs ) - 1 ] ;
    $ymin = minx ( $ys ) ;
    $ymax = maxx ( $ys ) ;
    $titl = "$show - $col - " . ( $ival == 'any' ? 'all data' : "last $ival" ) ;
    $subt = '' ;

    if ( $kind == 'spin' )
      { $scal = array (  0, 1.1 ) ; }
    elseif ( $kind == 'perc' )
      { $scal = array (  0, 100 ) ; }
    elseif ( $kind == 'temp' or $kind == 'volt' )
      { $scal = array (  $ymin - 0.5, $ymax + 0.5 ) ; }
    else
      { $scal = array (  0, 0 ) ; }

    $Ival = strtoupper ( substr ( $ival, 0, 1 ) ) ;
    if ( $ival != 'Y' and $ival != 'A' )
      { $grap -> SetScale ( 'datlin', $scal [ 0 ], $scal [ 1 ] ) ; }

    if ( $Ival == 'H' )
      { $grap -> xaxis -> scale -> SetTimeAlign ( MINADJ_10 ) ;
        $grap -> xaxis -> scale -> SetDateFormat ( 'H:i' ) ;
        $grap -> xaxis -> scale -> ticks -> Set ( 10*60 ) ;
      }
    elseif ( $Ival == 'D' )
      { $grap -> xaxis -> scale -> SetTimeAlign ( HOURADJ_1 ) ;
        $grap -> xaxis -> scale -> SetDateFormat ( 'H:00' ) ;
        $grap -> xaxis -> scale -> ticks -> Set ( 4*3600 ) ;
      }
    elseif ( $Ival == 'W' )
      { $grap -> xaxis -> scale -> SetDateAlign ( DAYADJ_1 ) ;
        $grap -> xaxis -> scale -> SetDateFormat ( 'D' ) ;
        $grap -> xaxis -> scale -> ticks -> Set ( 1*24*3600 ) ;
      }
    elseif ( $Ival == 'M' )
      { $grap -> xaxis -> scale -> SetDateAlign ( DAYADJ_7 ) ;
        $grap -> xaxis -> scale -> SetDateFormat ( '\w\e\e\k W' ) ;
        $grap -> xaxis -> scale -> ticks -> Set ( 7*24*3600 + 7200 ) ;
      }
    elseif ( $Ival == 'A' )
      { $grap -> xaxis -> scale -> SetDateAlign ( YEARADJ_1 ) ;
        $grap -> xaxis -> scale -> SetDateFormat ( 'Y' ) ;
        $grap -> xaxis -> scale -> ticks -> Set ( 366 * 24 * 3600 ) ;
      }
    elseif ( $Ival == 'Y' )
      { # printf ( "xmax %s [%s]<br>", $xmax, date ( 'r', $xmax ) ) ;
        $Y  = date ( 'Y', $xmax ) - 1 ;
        $aa = make_time ( array ( 'Y' => $Y ), $xmax ) ;
#       printf ( "aa %s [%s]<br>", $aa, date ( 'r', $aa ) ) ;
        $zz = first_of_next  ( $xmax ) + 2 * 3600 ;
#       printf ( "zz %s [%s]<br>", $zz, date ( 'r', $zz ) ) ;
        $grap -> SetScale ( 'intlin', $scal [ 0 ], $scal [ 1 ], $aa, $zz ) ;
        $tics = array () ;
        $labs = array () ;
        $frst = first_of_next ( $aa ) ;
        for ( $t = $frst ; $t <= $zz ; $t = first_of_next ( $t ) )
          { $tics [] = $t ; $labs [] = date ( 'M', $t ) ; }
        $grap -> xaxis -> SetMajTickPositions ( $tics, $labs) ;
      }
    elseif ( $Ival == 'A' )
      { # printf ( "xmax %s [%s]<br>", $xmax, date ( 'r', $xmax ) ) ;
        $aa = first_of_month ( $xmin ) ;
        $zz = first_of_next ( $xmax ) ;
        $Ya = date ( 'Y', $aa ) ;
        $Yz = date ( 'Y', $zz ) ;
        if ( $DEBUG )
        dmp ( "aa [$aa]", date ( 'r', $aa ) ) ;
        dmp ( "zz [$zz]", date ( 'r', $zz ) ) ;
        $grap -> SetScale
          ( 'intlin', $scal [ 0 ], $scal [ 1 ]
          , $aa - 24 * 3600, $zz + 24 * 3600
          ) ;
        $tics = array () ;
        $labs = array () ;
        if ( $Ya < $Yz )
          { for ( $t = $aa ; $t <= $zz ; $t = first_of_next ( $t, 12 ) )
              { $tics [] = $t ; $labs [] = date ( 'm/y', $t ) ; }
          }
        else
          { for ( $t = $aa + 1000 ; $t <= $zz ; $t = first_of_next ( $t, 1 ) )
              { $tics [] = $t ; $labs [] = date ( 'M', $t ) ; }
          }
        $grap -> xaxis -> SetMajTickPositions ( $tics, $labs) ;
      }

    if ( $Ival == 'Y' or $Ival == 'A' )
      { if ( $DEBUG )
          { for ( $i = 0 ; $i < count ( $tics ) ; $i++ )
              { $tic = $tics [ $i ] ;
                $lab = $labs [ $i ] ;
                dmp ( "tic [$tic] lab [$lab]" ) ;
              }
          }
      }

    if ( $kind == 'spin' )
      { $grap -> yaxis -> SetMajTickPositions
          ( array ( 0, 1 ) , array ( 'down', 'up' ) ) ;
      }

    if ( $kind == 'days' )
      { $subt = '[days]' ; }
    elseif ( $kind == 'msec' )
      { $subt = '[ms]' ; }
    elseif ( $kind == 'gbs' )
      { $subt = '[GB]' ; }
    elseif ( $kind == 'perc' )
      { $subt = '[%]' ; }

    $grap -> title -> Set ( $subt ? "$titl $subt" : $titl ) ;
    # left right top bottom
    $grap -> SetMargin ( 60, 20, 30, 20 ) ;
    $grap -> SetFrame ( true, 'black', 2 ) ;
    $grap -> SetMarginColor ( 'linen' ) ;
    $grap -> xaxis -> scale -> ticks -> SetColor ( 'red', 'black' ) ;
    $grap -> xgrid -> Show () ;

    // Set the angle for the labels to 90 degrees
#   $grap -> xaxis -> SetLabelAngle ( 90 ) ;

    $avgx = avgx ( $ys ) ;
    $curx = curx ( $ys ) ;
    $tcur = is_null ( $curx ) ? 'none' : sprintf ( "%.2f", $curx ) ;
    $tmin = is_null ( $ymin ) ? 'none' : sprintf ( "%.2f", $ymin ) ;
    $tmax = is_null ( $ymax ) ? 'none' : sprintf ( "%.2f", $ymax ) ;
    $tavg = is_null ( $avgx ) ? 'none' : sprintf ( "%.2f", $avgx ) ;
    $line = new LinePlot ( $ys, $xs ) ;
    $line -> SetLegend
      ( implode
          ( '      '
          , array ( "current:$tcur","min:$tmin","max:$tmax","average:$tavg" )
          )
      ) ;
    $line -> SetFillColor ( 'lightblue@0.5' ) ;
    $grap -> legend -> SetFillColor ( 'linen' ) ;
    $grap -> Add ( $line ) ;
    if ( ! $DEBUG )
      { header ( "Content-type: image/png" ) ;
        $grap -> Stroke () ;
      }
    exit ;
  }

function get_key ( $key, $def )
  { return array_key_exists ( $key, $_GET ) ? $_GET[$key] : $def ; }

# SERV=science-vs33.science.uu.nl&HOST=local-ups02.science.uu.nl&COLS=ups_temp
function mk_params ( &$SERV, &$WRKR, &$HOST, &$COLS, &$IVAL, &$KIND, &$SHOW )
  { # global $SERVER ;
    # get_key ( var, default )
    $SERV = get_key ( 'SERV', 'no_SERV' ) ;
    $WRKR = get_key ( 'WRKR', 'no_WRKR' ) ;
    $HOST = get_key ( 'HOST', 'no_HOST' ) ;
    $IVAL = get_key ( 'IVAL', 'H' ) ;
    $KIND = get_key ( 'KIND', 'real' ) ;
    $COLS = get_key ( 'COLS', '' ) ;
    $SHOW = get_key ( 'SHOW', $HOST ) ;
    if ( ! $COLS ) { croak ( 'no COLS' ) ; }
    $hpat = '/^[-._A-Za-z0-9]+$/' ;
    $npat = '/^[_A-Za-z0-9]+$/' ;
    if ( ! preg_match ( $hpat, $SERV ) ) { croak ( "bad SERV" ) ; }
    if ( ! preg_match ( $hpat, $WRKR ) ) { croak ( "bad WRKR" ) ; }
    if ( ! preg_match ( $hpat, $HOST ) ) { croak ( "bad HOST" ) ; }
    if ( ! preg_match ( $npat, $IVAL ) ) { croak ( "bad IVAL" ) ; }
    if ( ! preg_match ( $npat, $KIND ) ) { croak ( "bad KIND" ) ; }
    if ( ! preg_match ( $npat, $COLS ) ) { croak ( "bad COLS" ) ; }
  }

$SERV = '' ;
$WRKR = '' ;
$HOST = '' ;
$COLS = '' ;
$IVAL = '' ;
$KIND = '' ;
$DEBUG = get_key ( 'DEBUG', 0 ) ;
mk_params ( $SERV, $WRKR, $HOST, $COLS, $IVAL, $KIND, $SHOW ) ;
# $qwe  = "CLIENT $WRKR HIST $IVAL 100 $HOST $COLS" ;
# old : $mesg = get_mesg ( $SERVER, $PORT, $qwe ) ;
# new : $mesg = get_mesg ( $WRKR, $PORT+1, $qwe ) ;

$qwe  = "HIST $IVAL 100 $HOST $COLS" ;
$mesg =
  ( $SERV == 'localhost' 
  ? get_mesg ( $WRKR, $PORT+1, $qwe )
  : get_mesg ( $SERV, $PORT, "CLIENT $WRKR $qwe" )
  ) ;

if ( ( $cnt = count ( $mesg ) ) != 3 )
  { croak ( "insufficient mesg [$cnt]" ) ; }
elseif ( substr ( $mesg [ 1 ], 0, 1 ) != '{' )
  { $sub = substr ( $mesg [ 1 ], 0, 24 ) ;
    croak ( "bad mesg [$sub]" ) ;
  }
elseif ( $DEBUG )
  { dmp ( implode ( "<br>\n", $mesg ), 'mesg' ) ; }

$pvar = json_decode ( $mesg [ 1 ] ) ;
$resp = $pvar -> { 'resp' } ;

if ( json_last_error() !== JSON_ERROR_NONE ) 
  { croak ( 'json croaked ', substr ( $mesg [ 1 ], 0, 24 ) ) ; }
elseif ( ! $resp )
  { croak ( 'no response?' ) ; }
elseif ( substr ( $resp, 0, 2 ) != 'ok' )
  { croak ( $resp ) ; }

$data = $pvar -> data ;
$cols = $data -> cols ;
$rows = $data -> rows ;

gen_graph ( $cols, $rows, $HOST, $IVAL, $KIND, $SHOW ) ;

?>
