// 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.

var hg = require('mercury');
var h = require('mercury').h;
var request = require('superagent');
var cookie = require('cookie');

var pageHeaderComponent = require('./components/page-header');
var settingsPanelComponent = require('./components/settings');
var statusTableComponent = require('./components/status-table');
var metricActionsPanelComponent = require('./components/metric-actions-panel');

/**
 * A variable to store the most update-to-date dashboard data.
 *
 * We automatically retrive data from backend server every minute.
 */
var curData;

/**
 * A variable to keep track of current metric data shown in the
 * metric actions panel.
 */
var selectedMetricData;

// Ask mercury to listen to mousemove/mouseout/mouseover events.
hg.Delegator().listenTo('mousemove');
hg.Delegator().listenTo('mouseout');
hg.Delegator().listenTo('mouseover');

// Parse cookie.
var cookies = cookie.parse(document.cookie);

/** Top level state. */
var state = hg.state({
  // The header panel at the top of the page.
  pageHeader: pageHeaderComponent({
    startTimestamp: -1,
    endTimestamp: -1,
    oncallIds: ['_unknown', '_unknown'],
    loadingData: false,
    hasLoadingFailure: false
  }),

  components: hg.varhash({
    // The status table showing service status.
    statusTable: statusTableComponent(null),

    // The view showing data on the "instance" level.
    // instanceView: instanceViewComponent(null),
  }),

  // Whether to show settings panel.
  showSettingsPanel: hg.value(false),

  showMetricActionsPanel: hg.value(false),

  // Settings stored in cookies.
  settings: hg.varhash({
    darkTheme: hg.value(cookies.darkTheme === 'true')
  }),

  channels: {
    mouseClickOnMetric: mouseClickOnMetric,
    changeTheme: changeTheme,
    clickOnSettingsGear: clickOnSettingsGear,
    closeSettingsPanel: closeSettingsPanel,
    closeMetricActionsPanel: closeMetricActionsPanel
  }
});

/** Callback for clicking on a metric. */
function mouseClickOnMetric(state, data) {
  selectedMetricData = data;
  state.showMetricActionsPanel.set(true);
}

function closeMetricActionsPanel(state) {
  state.showMetricActionsPanel.set(false);
}

/** Callback when user clicks on the settings gear. */
function clickOnSettingsGear(state) {
  state.showSettingsPanel.set(true);
}

/** Callback when user closes the settings panel. */
function closeSettingsPanel(state) {
  state.showSettingsPanel.set(false);
}

/** Callback when user changes theme. */
function changeTheme(state, data) {
  document.cookie = cookie.serialize('darkTheme', data.darkTheme, {
    maxAge: '315360000' // ten years.
  });
  state.settings.darkTheme.set(data.darkTheme);
}

/** The main render function. */
var render = function(state) {
  var mainContent = [
    pageHeaderComponent.render(state.pageHeader),
  ];
  if (state.components.statusTable) {
    mainContent.push(
      h('div.main-container',
          statusTableComponent.render(state, state.components.statusTable))
    );
  }
  mainContent.push(
    h('div.settings-gear', {
      'ev-click': hg.send(state.channels.clickOnSettingsGear)
    })
  );
  if (state.showSettingsPanel) {
    mainContent.push(hg.partial(settingsPanelComponent.render, state));
  }

  if (state.showMetricActionsPanel) {
    mainContent.push(hg.partial(metricActionsPanelComponent.render, state,
          selectedMetricData, curData));
  }

  var className = state.settings.darkTheme ? 'main.darkTheme' : 'main';
  return h('div.' + className, mainContent);
};

/** Loads dashboard data from backend server. */
function loadData() {
  // Update data loading indicator.
  state.pageHeader.loadingData.set(true);

  // Get json dashboard data from "/data" endpoint.
  var dataEndpoint = window.location.origin + window.location.pathname + 'data';
  request
      .get(dataEndpoint)
      .accept('json')
      .timeout(30000)
      .end(function(err, res) {
    if (!res || !res.ok || err) {
      state.pageHeader.hasLoadingFailure.set(true);
    } else {
      state.pageHeader.hasLoadingFailure.set(false);
      processData(res.body);
    }
  });
}

/**
 * Callback function of loadData.
 * @param {Object} newData - Newly loaded data in json format.
 */
function processData(newData) {
  // Update components.
  curData = newData;
  updateComponents();

  // Update the data loading indicator.
  state.pageHeader.loadingData.set(false);
}

/**
 * Updates all page components.
 */
function updateComponents() {
  // Update page header.
  state.pageHeader.endTimestamp.set(curData.MaxTime);
  state.pageHeader.oncallIds.set(curData.Oncalls);

  // Update status table.
  var statusTableData = statusTableComponent({
    data: curData
  });
  state.components.put('statusTable', statusTableData);
}

// Add an event handler for closing settings panel when esc key is pressed.
document.onkeydown = function(evt) {
  if (evt.keyCode === 27) {
    if (state.showSettingsPanel()) {
      state.showSettingsPanel.set(false);
    }
    if (state.showMetricActionsPanel()) {
      state.showMetricActionsPanel.set(false);
    }
  }
};

hg.app(document.body, state, render);
loadData();
setInterval(loadData, 60000);
