package water.api;

import com.google.gson.*;
import water.*;

public class Cloud extends Request {

  public Cloud() {
    _requestHelp = "Displays the information about the current cloud. For each"
            + " node displays its heartbeat information.";
  }

  @Override public Response serve() {
    JsonObject response = new JsonObject();
    final H2O cloud = H2O.CLOUD;
    final H2ONode self = H2O.SELF;
    response.addProperty(VERSION, H2O.VERSION);
    response.addProperty(CLOUD_NAME, H2O.NAME);
    response.addProperty(NODE_NAME, self.toString());
    response.addProperty(CLOUD_SIZE, cloud._memary.length);
    JsonArray nodes = new JsonArray();
    for (H2ONode h2o : cloud._memary) {
      HeartBeat hb = h2o._heartbeat;
      JsonObject node = new JsonObject();
      node.addProperty(NAME,h2o.toString());
      node.addProperty(NUM_KEYS, hb._keys);
      node.addProperty(VALUE_SIZE, hb.get_valsz());
      node.addProperty(FREE_MEM, hb.get_free_mem());
      node.addProperty(TOT_MEM, hb.get_tot_mem());
      node.addProperty(MAX_MEM, hb.get_max_mem());
      node.addProperty(FREE_DISK, hb.get_free_disk());
      node.addProperty(MAX_DISK, hb.get_max_disk());
      node.addProperty(NUM_CPUS, (int)hb._num_cpus);
      node.addProperty(SYSTEM_LOAD, hb._system_load_average);

      JsonArray fjt = new JsonArray();
      JsonArray fjq = new JsonArray();
      if( hb._fjthrds_hi != null ) {
        for( int i=0; i<hb._fjthrds_hi.length; i++ ) {
          fjt.add(new JsonPrimitive(hb._fjthrds_hi[i]));
          fjq.add(new JsonPrimitive(hb._fjqueue_hi[i]));
        }
      }
      node.add(FJ_THREADS_HI, fjt);
      node.add(FJ_QUEUE_HI  , fjq);
      node.addProperty(FJ_THREADS_LO, (int)hb._fjthrds_lo);
      node.addProperty(FJ_QUEUE_LO, (int)hb._fjqueue_lo);
      node.addProperty(RPCS, (int)hb._rpcs);
      node.addProperty(TCPS_ACTIVE, (int) hb._tcps_active);
      node.addProperty(LAST_CONTACT,h2o._last_heard_from);
      nodes.add(node);
    }
    response.add(NODES,nodes);
    response.addProperty(CONSENSUS, Paxos._commonKnowledge); // Cloud is globally accepted
    response.addProperty(LOCKED, Paxos._cloudLocked); // Cloud is locked against changes
    Response r = Response.done(response);
    r.setBuilder(CONSENSUS, new BooleanStringBuilder("","Voting new members"));
    r.setBuilder(LOCKED, new BooleanStringBuilder("Locked","Accepting new members"));
    r.setBuilder(NODES, new MyAryBuilder());
    r.setBuilder(NODES+"."+NAME, new NodeCellBuilder());
    r.setBuilder(NODES+"."+LAST_CONTACT, new LastContactBuilder());
    return r;
  }

  public static String pos_neg(double d) {
    return d >= 0 ? String.valueOf(d) : "n/a";
  }

  // Just the Node as a link
  private static class NodeCellBuilder extends ArrayRowElementBuilder {
    @Override public String elementToString(JsonElement element, String contextName) {
      String str = element.getAsString();
      if( str.equals(H2O.SELF.toString()) )
        return "<a href='StoreView.html'>"+str+"</a>";
      return "<a href='Remote.html?Node="+str+"'>"+str+"</a>";
    }
  }
  // Highlight sick nodes
  private static class MyAryBuilder extends ArrayBuilder {
    static ArrayRowBuilder MY_ARRAY_ROW = new MyRowBuilder();
    @Override public Builder defaultBuilder(JsonElement element) { return MY_ARRAY_ROW; }
  }
  private static class MyRowBuilder extends ArrayRowBuilder {
    @Override public String header(JsonObject object, String objectName) {
      long then = object.getAsJsonPrimitive(LAST_CONTACT).getAsLong();
      long now = System.currentTimeMillis();
      return ((now-then) >= HeartBeatThread.TIMEOUT) ? "\n<tr class=\"error\">" : "\n<tr>";
    }
  }
  // Last-heard-from time pretty-printing
  private static class LastContactBuilder extends ArrayRowElementBuilder {
    @Override public String elementToString(JsonElement element, String contextName) {
      long then = element.getAsLong();
      long now = System.currentTimeMillis();
      return (now-then >= 2*1000) ? ""+((now-then)/1000)+" secs ago" : "now";
    }
  }
}

@@ -2956,17 +2956,19 @@
 ing()) )
+ %7B
 %0A
-
         
@@ -3024,63 +3024,178 @@
     
-return %22%3Ca href='Remote.html?Node=%22+str+%22'%3E%22+str+%22%3C/a%3E%22
+%7D%0A%0A      String str2 = str.startsWith(%22/%22) ? str.substring(1) : str;%0A      String str3 = %22%3Ca href='http://%22 + str2 + %22/StoreView.html'%3E%22 + str + %22%3C/a%3E%22;%0A      return str3
 ;%0A  

Fix broken StoreView link on cluster status page.