<?php

$cache = resin_create_distcache("resin:admin:graph");

$p_hash = htmlspecialchars($_REQUEST['h']);

$p_submit = $_REQUEST['submit'];
$p_graph = htmlspecialchars($_REQUEST['user-meters']);
$p_period = htmlspecialchars($_REQUEST['p']);
if ($_REQUEST['period'])
  $p_period = htmlspecialchars($_REQUEST['period']);

$p_servers = explode(" ", htmlspecialchars($_REQUEST['server-set']));
$user = quercus_servlet_request()->getRemoteUser();

$user_item = $cache->get($user);
$is_refresh = false;

if ($p_graph) {
  $p_hash = $user_item['user-graphs'][$p_graph];
  $p_submit = null;

  if ($_POST['remove']) {
    unset($user_item['user-graphs'][$p_graph]);
    $cache->put($user, $user_item);
  }

  $is_refresh = true;
}

if ($p_hash && ! $p_submit) {
  $item = $cache->get($p_hash);
  $p_name = $item['name'];
  $p_checks = $item['checks'];
}
else if ($p_submit) {
  $is_refresh = true;

  $p_name = htmlspecialchars($_REQUEST['name']);
  $p_checks = array_map(htmlspecialchars, $_REQUEST['checks']);

  $item = array("name"=>$p_name,
                "checks"=>$p_checks);

  $ser = serialize($item);
  $p_hash = dechex(crc32($ser));

  $cache->put($p_hash, $item);

  if ($p_submit) {
    $user_graphs = $user_item['user-graphs'];
    if ($user_graphs == null) {
      $user_graphs = array();
    }

    $user_graphs[$p_name] = $p_hash;
    $user_item['user-graphs'] = $user_graphs;

    $cache->put($user, $user_item);
  }
}

$query = "&h=" . $p_hash . "&p=" . $p_period;

require_once "WEB-INF/php/inc.php";

if (! admin_init($query, false)) {
  return;
}

echo "<h1>Graphs" . print_help("Graphs") . "</h1>\n";
$names = array();

$full_height = 500;
$full_width = 600;

$mbean_server = $g_mbean_server;

if (! $p_period) {
  $p_period = 60;
}

$self_index = sprintf("%02d", $g_server->SelfServer->ClusterIndex);

if ($p_servers == null) {
  $p_servers = array($self_index);
}

foreach ($p_checks as $check) {
  foreach ($p_servers as $server) {
    if ($server == 'self')
      $server = $self_index;
      
    $p_names[] = "$server|$check";
  }
}

if (! $p_name)
  $p_name = $p_names[0];

echo "<div id='canvas-warning'><p><b>Note:</b> this page requires HTML 5 
canvas support.  You may need to use Firefox 3.5 or other HTML 5-capable browser
to see the graphs properly.</p></div>\n";

$user_graphs = $user_item['user-graphs'];

echo "<div id='graph-content' style='display:none'>\n";

echo '<div id="new-graph-drawer">';
echo '<div id="new-graph-form">';
display_new_graph_form();
echo '</div>';
echo '</div>';

echo '<div style="float: left; width: %40;">';
display_main_graph();
echo '</div>';
echo "</div>";

display_footer($g_page, javascript_main_graph());

function display_graph_selection()
{
  global $p_period;
  global $p_hash;
  global $user_item;
  global $g_next_url;
  global $g_server;
  global $self_index;

  echo "<form name='def_graph' method='POST' action='" . $g_next_url . "'>";
  echo "<input type='hidden' name='period' value='$p_period'/>\n";
  echo "<b>Meters:</b>\n";

  echo "<select name='user-meters' onchange='javascript:document.forms.def_graph.submit();'>\n";

  $selected = false;
  foreach ($user_item['user-graphs'] as $name => $hash) {
    echo "<option ";
    if ($p_hash == $hash) {
      $selected = true;
      echo " selected";
    }
    echo " value='{$name}'>{$name}</option>\n";
  }
  if (! $selected)
    echo "<option selected>--------</option>\n";

  echo "</select>\n";

  $self_index = sprintf("%02d", $g_server->SelfServer->ClusterIndex);

  $cluster_size = count($g_server->Cluster->Servers);
  for ($i = 0; $i < $cluster_size; $i++) {
    if ($i > 0)
      $all .= ' ';

    $all .= sprintf("%02d", $i);
  }

  echo "<input type='hidden' name='server-self'"
       . " value='" . $self_index . "' />\n";
  echo "<input type='hidden' name='server-all'"
       . " value='" . $all . "' />\n";

  echo "<b>Server Set:</b>\n";
  echo "<select name='server-set'>\n";

  echo "<option value='self'";

  if ($_REQUEST['server-set'] == 'self')
    echo " selected";

  echo ">This Server</option>\n";

  echo "<option value='cluster'";

  if ($_REQUEST['server-set'] == 'cluster')
    echo " selected";

  echo ">All servers, multi-graph</option>\n";

  echo "<option value='combined'";

  if ($_REQUEST['server-set'] == 'combined')
    echo " selected";

  echo ">All servers, single graph</option>\n";

  echo "</select><br/>\n";

  echo "</form>";
}

function display_period_selection()
{
  global $p_period;
  global $g_next_url;

  echo "<div class='graph-period'>\n";

  echo "Time: "

  echo "<select name='period'>\n";

  echo " <option value='" . (60) . "'";

  if ($p_period == 60)
    echo " selected";

  echo ">1 hour</option>\n";

  echo " <option value='" . (6 * 60) . "'";

  if ($p_period == 6 * 60)
    echo " selected";

  echo ">6 hours</option>\n";

  echo " <option value='" . (24 * 60) . "'";

  if ($p_period == 24 * 60)
    echo " selected";

  echo ">24 hours</option>\n";

  echo " <option value='" . (7 * 24 * 60) . "'";

  if ($p_period == 7 * 24 * 60)
    echo " selected";

  echo ">7 days</option>\n";

  echo " <option value='" . (7 * 24 * 60) . "'";

  if ($p_period == 7 * 24 * 60)
    echo " selected";

  echo ">7 days</option>\n";

  echo "</select>\n";
  echo "</div>\n";
}

function display_main_graph() 
{
  global $g_next_url;
  global $p_name;
  global $p_graph;
  global $p_hash;
  global $p_period;

  display_period_selection();

  echo "<div class='graph'></div>";

  /*
   * XXX graph now requires flot -- include in rest output?
  if ($p_graph) {
    $rest_url = "rest.php?q=graph&graph={$p_graph}&period={$p_period}";

    echo "<div><a href='{$rest_url}'>Embedded graph URL</a></div>";
  }
  elseif ($p_hash) {
    $rest_url = "rest.php?q=graph&hash={$p_hash}&period={$p_period}";

    echo "<div><a href='{$rest_url}'>Embedded graph URL</a></div>";
  }*/

  echo "<br>";
}

function display_new_graph_form() 
{
  global $p_period;
  global $p_hash;
  global $p_graph;
  global $p_names;
  global $g_next_url;
  global $g_mbean_server;

  display_graph_selection();

  $stat = $g_mbean_server->lookup("resin:type=StatService");

  if (! $stat)
    return;

  $full_names = $stat->statisticsNames();

  $names = array();
  $servers = array();
  foreach ($full_names as $name) {
    $values = preg_split('/[|]/', $name);

    $server = array_shift($values);

    if (! in_array($server, $servers)) {
      $servers[] = $server;
    }
    
    $section_array = null;
    $section_array[] = array_shift($values);
    $section_array[] = array_shift($values);

    $section = join($section_array, '|');

    $name = join($values, '|');

    $names = $sections[$section];
    if (! in_array($name, $names))
      $names[] = $name;
    $sections[$section] = $names;
  }

  // server
  echo "<form name='name_form' method='post' action='" . $g_next_url . "'>"
  echo "<input type='hidden' name='submit' value='true'>\n";
  echo "<h2><span id='meter-switch' class='switch'></span>Meters</h2>";
  echo "<button id='clear-graph' style='margin: 0 1em'>Clear Meters</button>";

  $i = 0;

  ksort($sections);
  echo "<ul class='meters'>"
  foreach ($sections as $section => $names) {
    $i++;
    echo "<li class='meter-section'>";
    
    $section_id = "meter-" . crc32($section);
    echo "<span class='switch' id='$section_id'>$section</span>";

    sort($names);
    echo "<ul class='toggle-meter-switch toggle-$section_id'>";
    foreach ($names as $name) {
      echo "<li><input class='meter' type='checkbox' name='checks[]' ";

      $regexp = str_replace('|', '[|]', "/[0-9][0-9]|{$section}|{$name}/");

      if (preg_grep($regexp, $p_names)) {
        echo "checked ";
      }
        
      echo "value='$section|$name'>$name<br>\n";
    }
    echo "</ul>";
    echo "</li>";
  }
  echo "</ul>";

  echo "<div style='text-align: right'>\n";
  echo "<div id='validation-notice' class='ui-state-error ui-corner-all' style='display:none'></div>\n";
  echo "<input name='name' style='width: 100%;'>"
  echo "</input>\n";

  echo "<input type='submit' value='Save Meters'><br>\n";
  echo "</div>\n";

  echo "</form>\n";
}

function javascript_main_graph()
{
  global $g_next_url;

  $width = 600 - 60;
  $height = 400 - 40;

  $javascript = <<<EOF

if (document.createElement('canvas').getContext) {
  $("div#canvas-warning").hide();
  $("div#graph-content").show();
}

function GraphManager() {
  var graphDiv = $('div.graph');

  var updateGraph = function(element, canvasHtml) {
    if (canvasHtml.indexOf("<div") == 0) {
      element.empty();
      element.append(canvasHtml);
    }
    else {
      location.reload();
    }
  };

  var highlightSections = function() {
    $("li.meter-section").each(function() {
      var switchElement = $(this).find("span.switch");
      var meterCheckedCount = 
        $(this).find("input.meter:checkbox:checked").length;

      if (meterCheckedCount > 0) 
        switchElement.css("font-weight", "bold");
      else  
        switchElement.css("font-weight", "normal");
    });
  };

  var refresh = function() {
    highlightSections();

    var server_type = $("select[name=server-set] option:selected")
                        .attr("value");

    var servers;                        

    if (server_type == "self") {                     
      servers = [$("input[name=server-self]")
                   .attr("value")];
    }
    else {
      servers = $("input[name=server-all]")
                .attr("value")
                .split(" ");
    }

    var checks = $("input.meter:checkbox:checked").map(function() {
      return $(this).attr("value");
    });

    var period = $("select[name=period] option:selected").attr("value");

    // synchronize the period in the hidden input in the Meters form
    $("input[name=period]").attr("value", period);

    var isMultiGraph = 
      ($("select[name=server-set] option:selected").attr("value") == "cluster");

    if (isMultiGraph) {
      graphDiv.empty();

      $.each(servers, function(i, server) {
        var element = $("<div></div>");
        graphDiv.append(element);

        $.post("rest.php?q=graph",
               { canvas : "graph-" + server,
                 servers: [ server ],
                 checks : checks,
                 period : period,
                 width : "${width}",
                 height : "${height}" },
               function(canvasHtml) {
                 updateGraph(element, canvasHtml);
               },
               "text/html");
      });
    }
    else {
      $.post("rest.php?q=graph",
             { canvas : "graph-" + servers.join("-"),
               servers: servers,
               checks : checks,
               period : period,
               width : "${width}",
               height : "${height}" },
             function(canvasHtml) {
               updateGraph(graphDiv, canvasHtml);
             },
             "text/html");
    }   
  };

  refresh();
  window.setInterval(refresh, 60000);

  $("input.meter:checkbox").change(refresh);
  $("form[name=def_graph] :input:not(input[type=hidden])").change(refresh);
  $("select[name=period]").change(refresh);

  $("button#clear-graph").click(function() {
    $("input.meter:checkbox:checked").each(function() {
      $(this).attr("checked", false);
      $(this).change();
    });
    
    return false;
  });

  var nameInput = $("input[name=name]");

  nameInput.attr("value", "Meter Set Name");
  nameInput.css("color", "#999");
  nameInput.focusin(function() {
    if (nameInput.attr("value") == "Meter Set Name") {
      nameInput.attr("value", "");
      nameInput.css("color", "black");
    }
  });

  nameInput.focusout(function() {
    if (nameInput.attr("value") == "") {
      nameInput.attr("value", "Meter Set Name");
      nameInput.css("color", "#999");
    }
  });

  var validationNotice = $("#validation-notice");
  nameInput.closest("form").submit( function() {
    var html = "";

    if ($("input.meter:checkbox:checked").length == 0) {
      html += "Please select at least one meter for this set<br/>";
    }

    if (nameInput.attr("value") == "Meter Set Name"
        || nameInput.attr("value") == "") {
      html += "Please input a name for this meter set<br/>";
    }

    if (html != "") {
      validationNotice.html(html);
      validationNotice.show();
      return false;
    }
  });
}

new GraphManager();

EOF;

  return $javascript;
}

?>
