// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

/** Information about a particular waterfall. */
function WaterfallInfo(waterfallData) {
  var waterfallName = waterfallData[0];
  var waterfallUrl = waterfallData[1];
  var waterfallShowsAllBots = waterfallData[2];

  // Create a table cell that acts as a header for its bot section.
  var linkElement = document.createElement('a');
  linkElement.href = waterfallUrl;
  linkElement.innerHTML = waterfallName;
  var thElement = document.createElement('th');
  thElement.colSpan = 15;
  thElement.className = 'section-header';
  thElement.appendChild(linkElement);

  this.botInfo = {};
  this.inFlight = 0;
  this.name = waterfallName;
  this.showsAllBots = waterfallShowsAllBots;
  this.thElement = thElement;
  this.timeLastRequested = 0;
  this.rootJsonUrl = waterfallUrl + 'json/';
  this.url = waterfallUrl;
}

/** Send an asynchronous request to get the main waterfall's JSON. */
WaterfallInfo.prototype.requestJson = function() {
  if (this.inFlight) {
    var elapsed = new Date().getTime() - this.timeLastRequested;
    if (elapsed < MAX_MILLISECONDS_TO_WAIT) return;

    // A response was not received in a reasonable timeframe. Try again.
    this.inFlight--;
    gNumRequestsInFlight--;
    gNumRequestsRetried++;
  }

  this.inFlight++;
  this.timeLastRequested = new Date().getTime();
  gNumRequestsInFlight++;

  // Create the request and send it off.
  var waterfallInfo = this;
  var url = this.url + 'json/builders/';
  var request = new XMLHttpRequest();
  request.open('GET', url, true);
  request.onreadystatechange = function() {
    if (request.readyState == 4 && request.status == 200) {
      waterfallInfo.parseJSON(JSON.parse(request.responseText));
    }
  };
  request.send(null);
};

/** Parse out the data received about the waterfall. */
WaterfallInfo.prototype.parseJSON = function(buildersJson) {
  this.inFlight--;
  gNumRequestsInFlight--;

  // Go through each builder on the waterfall and get the latest status.
  var builderNames = Object.keys(buildersJson);
  for (var i = 0; i < builderNames.length; ++i) {
    var builderName = builderNames[i];

    if (!this.showsAllBots && !this.shouldShowBot(builderName)) continue;

    // Prepare the bot info.
    var builderJson = buildersJson[builderName];
    if (!this.botInfo[builderName]) {
      this.botInfo[builderName] = new BotInfo(builderName,
                                              builderJson.category);
    }
    this.botInfo[builderName].update(this.rootJsonUrl, builderJson);
    gWaterfallDataIsDirty = true;
  }
};

/** Override this function to filter out particular bots. */
WaterfallInfo.prototype.shouldShowBot = function(builderName) {
  return true;
};

/** Updates the HTML. */
WaterfallInfo.prototype.updateWaterfallStatusHTML = function() {
  var table = document.getElementById('build-info');

  // Point at the waterfall.
  var headerCell = this.thElement;
  headerCell.className =
      'section-header' + (this.inFlight > 0 ? ' in-flight' : '');
  var headerRow = table.insertRow(-1);
  headerRow.appendChild(headerCell);

  // Print out useful bits about the bots.
  var botNames = sortBotNamesByCategory(this.botInfo);
  for (var i = 0; i < botNames.length; ++i) {
    var botName = botNames[i];
    var botInfo = this.botInfo[botName];
    var waterfallBaseUrl = this.url + 'builders/';

    var botRowElement = botInfo.createHtml(waterfallBaseUrl);

    // Determine whether we should apply keyword filter.
    var filter = document.getElementById('text-filter').value.trim();
    if (filter.length > 0) {
      var keywords = filter.split(' ');
      var buildNumbers = Object.keys(botInfo.builds);
      var matchesFilter = false;

      for (var x = 0; x < buildNumbers.length && !matchesFilter; ++x) {
        var buildStatus = botInfo.builds[buildNumbers[x]].statusText;
        for (var y = 0; y < keywords.length && !matchesFilter; ++y) {
          if (buildStatus.indexOf(keywords[y]) >= 0)
            matchesFilter = true;
        }
      }

      if (!matchesFilter)
        continue;
    }

    // If the user doesn't want to see completely green bots, hide it.
    var shouldHideStable =
        document.getElementById('checkbox-hide-stable').checked;
    if (shouldHideStable && botInfo.isSteadyGreen)
      continue;

    table.appendChild(botRowElement);
  }
};