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

/**
 * Columns of the summary table.
 */

var hg = require('mercury');
var h = require('mercury').h;
var svg = require('virtual-dom/virtual-hyperscript/svg');

var AppStateMgr = require('../../appstate-manager');
var Consts = require('../../constants');
var MouseMoveHandler = require('../../mousemove-handler.js');
var Util = require('../../util');
var summaryTableMetricNamesColumnComponent = require('./metricnames-column');

module.exports = {
  render: render
};

/** The main render function. */
function render(state) {
  var data = state.data.Zones;
  var level = AppStateMgr.getAppState('level');

  var cols = [hg.partial(summaryTableMetricNamesColumnComponent.render, state)];
  if (level === 'global') {
    cols = cols.concat(genCellsInGlobalLevel(state, data));
  } else if (level === 'zone') {
    cols = cols.concat(genCellsInZoneLevel(state, data));
  }
  return h('div.columns-container', cols);
}

/** Generates data cells in the "globel" level. */
function genCellsInGlobalLevel(state, data) {
  var aggType = AppStateMgr.getAppState('globalLevelAggType');
  var cols = Consts.orderedZones.filter(function(zone) {
    return data[zone];
  }).map(function(zone) {
    var aggData = data[zone][aggType];
    var rows = [];
    Consts.mainMetrics.forEach(function(curMetric, index) {
      var dataKey = curMetric.dataKey;
      var metricKey = curMetric.metricKey;
      if (!Util.isEmptyObj(aggData[dataKey])) {
        rows.push(renderCell(
            state, aggData, aggData.Range.MinTime, aggData.Range.MaxTime,
            dataKey, metricKey, zone, zone));
      } else {
        rows.push(renderFillerCell(state));
      }
      if (curMetric.addMinorDivider) {
        rows.push(h('div.minor-divider'));
      }
      if (curMetric.addMajorDivider) {
        rows.push(h('div.major-divider'));
      }
    });
    return h('div.zone-col', rows);
  });
  return cols;
}

/** Generates data cells in the "zone" level. */
function genCellsInZoneLevel(state, data) {
  var zoneLevelZone = AppStateMgr.getAppState('zoneLevelZone');
  var zoneLevelType = AppStateMgr.getAppState('zoneLevelType');

  // Filter metrics and instances by zone level type (CloudService or Nginx).
  var metrics = (zoneLevelType === 'CloudService' ?
      Consts.cloudServiceMetrics.concat(Consts.cloudServiceGCEMetrics) :
      Consts.nginxMetrics.concat(Consts.nginxGCEMetrics));
  var instancePrefix = (zoneLevelType === 'CloudService' ?
      'vanadium-' : 'nginx-');
  var instanceNames = Object.keys(data[zoneLevelZone].Instances);
  var cols = instanceNames.sort().filter(function(name) {
    return name.startsWith(instancePrefix);
  }).map(function(instance) {
    var instanceData = data[zoneLevelZone].Instances[instance];
    var rows = [];
    // Calculate the min/max timestamps across all metrics.
    var minTime = Number.MAX_VALUE;
    var maxTime = 0;
    metrics.forEach(function(curMetric) {
      var dataKey = curMetric.dataKey;
      var metricKey = curMetric.metricKey;
      if (!Util.isEmptyObj(instanceData[dataKey])) {
        var metricData = instanceData[dataKey][metricKey];
        if (metricData) {
          if (metricData.MinTime < minTime) {
            minTime = metricData.MinTime;
          }
          if (metricData.MaxTime > maxTime) {
            maxTime = metricData.MaxTime;
          }
        }
      }
    });
    metrics.forEach(function(curMetric, index) {
      var dataKey = curMetric.dataKey;
      var metricKey = curMetric.metricKey;
      if (!Util.isEmptyObj(instanceData[dataKey])) {
        rows.push(renderCell(
            state, instanceData, minTime, maxTime,
            dataKey, metricKey, instance, zoneLevelZone));
      } else {
        rows.push(renderFillerCell(state));
      }
      if (curMetric.addMinorDivider) {
        rows.push(h('div.minor-divider'));
      }
      if (curMetric.addMajorDivider) {
        rows.push(h('div.major-divider'));
      }
    });
    return h('div.zone-col', rows);
  });
  return cols;
}

/**
 * Renders a single table cell.
 * @param {hg.state} state - The component's state.
 * @param {Object} cellData - The data object for the cell.
 * @param {Number} minTime - The minimum time to render the sparkline for.
 * @param {Number} maxTime - The maximum time to render the sparkline for.
 * @param {string} dataKey - See comments of createMetric function in
 *     constants.js.
 * @param {string} metricKey - See comments of createMetric function in
 *     constants.js.
 * @param {string} column - The column name of the cell.
 * @param {string} zone - The zone name associated with the cell.
 */
function renderCell(state, cellData, minTime, maxTime,
    dataKey, metricKey, column, zone) {
  var data = cellData[dataKey][metricKey];
  var health = 'unhealthy';
  if (data) {
    health = (data.Healthy ? 'healthy' : 'unhealthy');
  }

  // 100 is the default logical width of any svg graphs.
  var points = '0,100 100,100';
  var mouseOffset = 100 * state.mouseMoveCellData.offsetFactor;
  var mouseEventData = {column: column, dataKey: dataKey, metricKey: metricKey};
  if (data && data.HistoryTimestamps) {
    points = Util.genPolylinePoints(
      data.HistoryTimestamps, data.HistoryValues,
      minTime, maxTime, data.MinValue, data.MaxValue);
  }

  // Show mouse line based on the dataKey type (CloudService or Nginx).
  var mouseMoveOnCloudServices =
      state.mouseMoveCellData.dataKey.startsWith('CloudService');
  var mouseMoveOnNginx = state.mouseMoveCellData.dataKey.startsWith('Nginx');
  var showMouseLine = (column === state.mouseMoveCellData.column &&
      ((dataKey.startsWith('CloudService') && mouseMoveOnCloudServices) ||
       (dataKey.startsWith('Nginx') && mouseMoveOnNginx)));

  var curValue = data ? data.CurrentValue : 0;
  var curValueClass = 'value';
  if (data && showMouseLine) {
    curValue = Util.interpolateValue(
        data.CurrentValue, state.mouseMoveCellData.offsetFactor,
        data.HistoryTimestamps, data.HistoryValues);
    curValueClass += '.history';
  }
  var formattedCurValue = data ? Util.formatValue(curValue) : '?';
  var items = [
    h('div.highlight-overlay'),
    h('div.mouse-line', showMouseLine ? renderMouseLine(mouseOffset) : []),
    h('div.sparkline', {
      'ev-mousemove': new MouseMoveHandler(
          state.channels.mouseMoveOnSparkline, mouseEventData),
      'ev-mouseout': hg.send(state.channels.mouseOutOfSparkline)
    }, renderSparkline(points)),
    h('div.' + curValueClass, formattedCurValue)
  ];

  var cellClassName = 'zone-col-cell.cell.' + health;
  return h('div.' + cellClassName, {
    'ev-mouseout': hg.send(state.channels.mouseOutOfTableCell),
    'ev-mouseover': hg.send(state.channels.mouseOverTableCell, mouseEventData),
    'ev-click': hg.send(state.channels.clickCell, {
      column: column,
      dataKey: dataKey,
      zone: zone
    })
  }, items);
}

/** Renders a empty filler table cell. */
function renderFillerCell(state) {
  return h('div.zone-col-cell-filler.cell', {
    'ev-mouseout': hg.send(state.channels.mouseOutOfTableCell)
  });
}

/**
 * Renders sparkline for the given points.
 * @param {string} points - A string in the form of "x1,y1 x2,y2 ...".
 */
function renderSparkline(points) {
  return svg('svg', {
    'class': 'content',
    'viewBox': '0 0 100 100',
    'preserveAspectRatio': 'none'
  }, [
    svg('polyline', {'points': points}),
  ]);
}

/**
 * Renders mouse line at the given offset.
 * @param {Number} mouseOffset - The logical offset for the mouse line.
 */
function renderMouseLine(mouseOffset) {
  return svg('svg', {
    'class': 'mouse-line',
    'viewBox': '0 0 100 100',
    'preserveAspectRatio': 'none'
  }, [
    svg('polyline', {
      'points': mouseOffset + ',0 ' + mouseOffset + ',100'
    })
  ]);
}
