// Copyright (c) 2013 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.

/**
 * Main entry point called once the page has loaded.
 */
function onLoad() {
  NetExportView.getInstance();
}

document.addEventListener('DOMContentLoaded', onLoad);

/**
 * This class handles the presentation of the net-export view. Used as a
 * singleton.
 */
var NetExportView = (function() {
  'use strict';

  // --------------------------------------------------------------------------

  var kIdStateDivUninitialized = 'state-uninitialized';
  var kIdStateDivInitial = 'state-initial';
  var kIdStateDivLogging = 'state-logging';
  var kIdStateDivStopped = 'state-stopped';
  var kIdStartLoggingButton = 'start-logging';
  var kIdStopLoggingButton = 'stop-logging';
  var kIdEmailLogButton = 'mobile-email';
  var kIdShowFileButton = 'show-file';
  var kIdCaptureModeLogging = 'capture-mode-logging';
  var kIdFilePathLogging = 'file-path-logging';
  var kIdCaptureModeStopped = 'capture-mode-stopped';
  var kIdFilePathStoppedLogging = 'file-path-stopped';
  var kIdStartOverButton = 'startover';
  var kIdPrivacyReadMoreLink = 'privacy-read-more-link';
  var kIdPrivacyReadMoreDiv = 'privacy-read-more'
  var kIdTooBigReadMoreLink = 'toobig-read-more-link';
  var kIdTooBigReadMoreDiv = 'toobig-read-more'
  var kIdLogMaxFileSizeInput = 'log-max-filesize'

  /**
   * @constructor
   */
  function NetExportView() {
    // Tell NetExportMessageHandler to notify the UI of future state changes
    // from this point on (through onExportNetLogInfoChanged()).
    chrome.send('enableNotifyUIWithState');

    this.infoForLoggedFile_ = null;
  }

  cr.addSingletonGetter(NetExportView);

  NetExportView.prototype = {
    /**
     * Starts saving NetLog data to a file.
     */
    onStartLogging_: function() {
      // Determine the capture mode to use.
      var logMode =
          document.querySelector('input[name="log-mode"]:checked').value;

      // Determine the maximum file size, as the number of bytes (or -1 to mean
      // no limit)
      var maxLogFileSizeBytes = -1;
      var fileSizeString = $(kIdLogMaxFileSizeInput).value;
      var numMegabytes = parseFloat(fileSizeString);
      if (!isNaN(numMegabytes)) {
        // Convert to an integral number of bytes.
        maxLogFileSizeBytes = Math.round(numMegabytes * 1024 * 1024);
      }

      chrome.send('startNetLog', [logMode, maxLogFileSizeBytes]);
    },

    /**
     * Stops saving NetLog data to a file.
     */
    onStopLogging_: function() {
      chrome.send('stopNetLog');
    },

    /**
     * Sends NetLog data via email from browser (mobile only).
     */
    onSendEmail_: function() {
      chrome.send('sendNetLog');
    },

    /**
     * Reveals the log file in the shell (i.e. selects it in the Finder on
     * Mac).
     */
    onShowFile_: function() {
      chrome.send('showFile');
    },

    /**
     * Transitions back to the "Start logging to disk" state.
     */
    onStartOver_: function() {
      this.infoForLoggedFile_ = null;
      this.renderInitial_();
    },

    /**
     * Updates the UI to reflect the current state. The state transitions are
     * sent by the browser controller (NetLogFileWriter):
     *
     *   * UNINITIALIZED - This is the initial state when net-export is opened
     *         for the first time, or there was an error during initialization.
     *         This state is short-lived and likely not observed; will
     *         immediately transition to INITIALIZING).
     *
     *   * INITIALIZING - On desktop UI this is pretty much a no-op. On the
     *         mobile UI, this state is when the controller checks the disk for
     *         a previous net-log file (from past run of the browser). After
     *         success will transition to NOT_LOGGING. On failure will
     *         transition to UNINITIALIZED (rare).
     *
     *   * NOT_LOGGING - This is the steady-state. It means initialization
     *        completed and we are not currently logging. Being in this state
     *        either means:
     *         (1) We were logging and then the user stopped (earlier states
     *             were STATE_LOGGING / STATE_STOPPING_LOG).
     *         (2) We have never started logging (previous state was
     *             INITIALIZING).
     *
     *   * STARTING_LOG - This state means the user has clicked the "Start log"
     *        button and logging is about to get started (files may not have
     *        been created yet).
     *
     *   * LOGGING - This state means that logging is currently in progress.
     *        The destination path of the log, and the capture mode are known
     *        and will be reflected in the parameters.
     *
     *   * STOPPING_LOG - This state means the user has clicked the "Stop
     *        logging" button, and the log file is in the process of being
     *        finalized. Once the state transitions to NOT_LOGGING then the log
     *        is complete, and can safely be copied/emailed.
     */
    onExportNetLogInfoChanged: function(info) {
      switch (info.state) {
        case 'UNINITIALIZED':
        case 'INITIALIZING':
          this.renderUninitialized_();
          break;

        case 'NOT_LOGGING':
          if (this.infoForLoggedFile_) {
            // There is no "stopped logging" state. We manufacture that in the
            // UI in response to a transition from LOGGING --> NOT_LOGGING.
            this.renderStoppedLogging_(this.infoForLoggedFile_);

            // TODO(eroman): prevent future state transitions. In desktop UI
            // could start logging in a new tab, and it would reset this one.
          } else if (info.logExists) {
            // In the mobile UI, initialization may have found a
            // pre-existing log file.
            this.renderStoppedLogging_(info);
          } else {
            this.renderInitial_();
          }
          break;

        case 'STARTING_LOG':
          // This is a short-lived state, no need to do anything special.
          // Disabling the buttons would be nice, however it is not crucial as
          // the controller will reject commands while in this state anyway.
          this.renderInitial_();
          break;

        case 'LOGGING':
          // Cache the last information for this logging session, so once
          // logging is stopped will know what path information to display.
          this.infoForLoggedFile_ = info;
          this.renderLogging_(info);
          break;

        case 'STOPPING_LOG':
          // This is a short-lived state, no need to do anything special.
          this.renderLogging_(info);
          break;
      }
    },

    /**
     * Updates the UI to display the "uninitialized" state. This is only
     * visible for a short period of time, or longer if initialization failed
     * (and didn't transition to a different state).
     */
    renderUninitialized_: function() {
      this.showStateDiv_(kIdStateDivUninitialized);
    },

    /**
     * Updates the UI to display the "initial" state. This is the state when
     * logging has not been started yet, and there are controls to start
     * logging.
     */
    renderInitial_: function() {
      this.showStateDiv_(kIdStateDivInitial);
      $(kIdStartLoggingButton).onclick = this.onStartLogging_.bind(this);
    },

    /**
     * Updates the UI to display the "logging" state. This is the state while
     * capturing is in progress and being written to disk.
     */
    renderLogging_: function(info) {
      this.showStateDiv_(kIdStateDivLogging);

      $(kIdStopLoggingButton).onclick = this.onStopLogging_.bind(this);
      $(kIdCaptureModeLogging).textContent = this.getCaptureModeText_(info);
      $(kIdFilePathLogging).textContent = info.file;
    },

    /*
     * Updates the UI to display the state when logging has stopped.
     */
    renderStoppedLogging_: function(info) {
      this.showStateDiv_(kIdStateDivStopped);

      // The email button is only available in the mobile UI.
      if ($(kIdEmailLogButton))
        $(kIdEmailLogButton).onclick = this.onSendEmail_.bind(this);
      // The show file button is only available in the desktop UI.
      if ($(kIdShowFileButton))
        $(kIdShowFileButton).onclick = this.onShowFile_.bind(this);
      $(kIdStartOverButton).onclick = this.onStartOver_.bind(this);

      $(kIdFilePathStoppedLogging).textContent = info.file;

      $(kIdCaptureModeStopped).textContent = this.getCaptureModeText_(info);

      // Hook up the "read more..." link for privacy information.
      $(kIdPrivacyReadMoreLink).onclick =
          this.showPrivacyReadMore_.bind(this, true);
      this.showPrivacyReadMore_(false);

      // Hook up the "read more..." link for reducing log size information.
      $(kIdTooBigReadMoreLink).onclick =
          this.showTooBigReadMore_.bind(this, true);
      this.showTooBigReadMore_(false);
    },

    /**
     * Gets the textual label for a capture mode from the HTML.
     */
    getCaptureModeText_: function(info) {
      // TODO(eroman): Should not hardcode "Unknown" (will not work properly if
      //               the HTML is internationalized).
      if (!info.logCaptureModeKnown)
        return "Unknown";

      var radioButton = document.querySelector(
          'input[name="log-mode"][value="' + info.captureMode + '"]');
      if (!radioButton)
        return 'Unknown';
      return radioButton.parentElement.textContent;
    },

    showPrivacyReadMore_: function(show) {
      $(kIdPrivacyReadMoreDiv).hidden = !show;
      $(kIdPrivacyReadMoreLink).hidden = show;
    },

    showTooBigReadMore_: function(show) {
      $(kIdTooBigReadMoreDiv).hidden = !show;
      $(kIdTooBigReadMoreLink).hidden = show;
    },

    showStateDiv_: function(divId) {
      var kAllDivIds = [
        kIdStateDivUninitialized,
        kIdStateDivInitial,
        kIdStateDivLogging,
        kIdStateDivStopped
      ];

      for (var curDivId of kAllDivIds) {
        $(curDivId).hidden = divId != curDivId;
      }
    },
  };

  return NetExportView;
})();
