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

'use strict';

/** @suppress {duplicate} */
var remoting = remoting || {};

/**
 * @param {Array.<remoting.HostSetupFlow.State>} sequence Sequence of
 *     steps for the flow.
 * @constructor
 */
remoting.HostSetupFlow = function(sequence) {
  this.sequence_ = sequence;
  this.currentStep_ = 0;
  this.state_ = sequence[0];
  this.pin = '';
  this.consent = false;
};

/** @enum {number} */
remoting.HostSetupFlow.State = {
  NONE: 0,

  // Dialog states.
  ASK_PIN: 1,

  // Prompts the user to install the host package.
  INSTALL_HOST: 2,

  // Processing states.
  STARTING_HOST: 3,
  UPDATING_PIN: 4,
  STOPPING_HOST: 5,

  // Done states.
  HOST_STARTED: 6,
  UPDATED_PIN: 7,
  HOST_STOPPED: 8,

  // Failure states.
  REGISTRATION_FAILED: 9,
  START_HOST_FAILED: 10,
  UPDATE_PIN_FAILED: 11,
  STOP_HOST_FAILED: 12
};

/** @return {remoting.HostSetupFlow.State} Current state of the flow. */
remoting.HostSetupFlow.prototype.getState = function() {
  return this.state_;
};

remoting.HostSetupFlow.prototype.switchToNextStep = function() {
  if (this.state_ == remoting.HostSetupFlow.State.NONE) {
    return;
  }

  if (this.currentStep_ < this.sequence_.length - 1) {
    this.currentStep_ += 1;
    this.state_ = this.sequence_[this.currentStep_];
  } else {
    this.state_ = remoting.HostSetupFlow.State.NONE;
  }
};

/**
 * @param {remoting.Error} error
 */
remoting.HostSetupFlow.prototype.switchToErrorState = function(error) {
  if (error == remoting.Error.CANCELLED) {
    // Stop the setup flow if user rejected one of the actions.
    this.state_ = remoting.HostSetupFlow.State.NONE;
  } else {
    // Current step failed, so switch to corresponding error state.
    if (this.state_ == remoting.HostSetupFlow.State.STARTING_HOST) {
      if (error == remoting.Error.REGISTRATION_FAILED) {
        this.state_ = remoting.HostSetupFlow.State.REGISTRATION_FAILED;
      } else {
        this.state_ = remoting.HostSetupFlow.State.START_HOST_FAILED;
      }
    } else if (this.state_ == remoting.HostSetupFlow.State.UPDATING_PIN) {
      this.state_ = remoting.HostSetupFlow.State.UPDATE_PIN_FAILED;
    } else if (this.state_ == remoting.HostSetupFlow.State.STOPPING_HOST) {
      this.state_ = remoting.HostSetupFlow.State.STOP_HOST_FAILED;
    } else {
      // TODO(sergeyu): Add other error states and use them here.
      this.state_ = remoting.HostSetupFlow.State.START_HOST_FAILED;
    }
  }
};

/**
 * @param {remoting.HostController} hostController The HostController
 * responsible for the host daemon.
 * @constructor
 */
remoting.HostSetupDialog = function(hostController) {
  this.hostController_ = hostController;
  this.pinEntry_ = document.getElementById('daemon-pin-entry');
  this.pinConfirm_ = document.getElementById('daemon-pin-confirm');
  this.pinErrorDiv_ = document.getElementById('daemon-pin-error-div');
  this.pinErrorMessage_ = document.getElementById('daemon-pin-error-message');

  /** @type {remoting.HostSetupFlow} */
  this.flow_ = new remoting.HostSetupFlow([remoting.HostSetupFlow.State.NONE]);

  /** @type {remoting.HostSetupDialog} */
  var that = this;
  /** @param {Event} event The event. */
  var onPinSubmit = function(event) {
    event.preventDefault();
    that.onPinSubmit_();
  };
  var onPinConfirmFocus = function() {
    that.validatePin_();
  };

  var form = document.getElementById('ask-pin-form');
  form.addEventListener('submit', onPinSubmit, false);
  /** @param {Event} event The event. */
  var onDaemonPinEntryKeyPress = function(event) {
    if (event.which == 13) {
      document.getElementById('daemon-pin-confirm').focus();
      event.preventDefault();
    }
  };
  /** @param {Event} event A keypress event. */
  var noDigitsInPin = function(event) {
    if (event.which == 13) {
      return;  // Otherwise the "submit" action can't be triggered by Enter.
    }
    if ((event.which >= 48) && (event.which <= 57)) {
      return;
    }
    event.preventDefault();
  };
  this.pinEntry_.addEventListener('keypress', onDaemonPinEntryKeyPress, false);
  this.pinEntry_.addEventListener('keypress', noDigitsInPin, false);
  this.pinConfirm_.addEventListener('focus', onPinConfirmFocus, false);
  this.pinConfirm_.addEventListener('keypress', noDigitsInPin, false);

  this.usageStats_ = document.getElementById('usagestats-consent');
  this.usageStatsCheckbox_ = /** @type {HTMLInputElement} */
      document.getElementById('usagestats-consent-checkbox');
};

/**
 * Show the dialog in order to get a PIN prior to starting the daemon. When the
 * user clicks OK, the dialog shows a spinner until the daemon has started.
 *
 * @return {void} Nothing.
 */
remoting.HostSetupDialog.prototype.showForStart = function() {
  /** @type {remoting.HostSetupDialog} */
  var that = this;

  /**
   * @param {remoting.HostController.State} state
   */
  var onState = function(state) {
    // Although we don't need an access token in order to start the host,
    // using callWithToken here ensures consistent error handling in the
    // case where the refresh token is invalid.
    remoting.identity.callWithToken(
        that.showForStartWithToken_.bind(that, state),
        remoting.showErrorMessage);
  };

  this.hostController_.getLocalHostState(onState);
};

/**
 * @param {remoting.HostController.State} state The current state of the local
 *     host.
 * @param {string} token The OAuth2 token.
 * @private
 */
remoting.HostSetupDialog.prototype.showForStartWithToken_ =
    function(state, token) {
  /** @type {remoting.HostSetupDialog} */
  var that = this;

  /**
   * @param {boolean} supported True if crash dump reporting is supported by
   *     the host.
   * @param {boolean} allowed True if crash dump reporting is allowed.
   * @param {boolean} set_by_policy True if crash dump reporting is controlled
   *     by policy.
   */
  function onGetConsent(supported, allowed, set_by_policy) {
    that.usageStats_.hidden = !supported;
    that.usageStatsCheckbox_.checked = allowed;
    that.usageStatsCheckbox_.disabled = set_by_policy;
  }

  /** @param {remoting.Error} error */
  function onError(error) {
    console.error('Error getting consent status: ' + error);
  }

  this.usageStats_.hidden = false;
  this.usageStatsCheckbox_.checked = false;

  // Prevent user from ticking the box until the current consent status is
  // known.
  this.usageStatsCheckbox_.disabled = true;

  this.hostController_.getConsent(onGetConsent, onError);

  var flow = [
      remoting.HostSetupFlow.State.INSTALL_HOST,
      remoting.HostSetupFlow.State.ASK_PIN,
      remoting.HostSetupFlow.State.STARTING_HOST,
      remoting.HostSetupFlow.State.HOST_STARTED];

  var installed =
      state != remoting.HostController.State.NOT_INSTALLED &&
      state != remoting.HostController.State.INSTALLING;

  // Skip the installation step when the host is already installed.
  if (installed) {
    flow.shift();
  }

  this.startNewFlow_(flow);
};

/**
 * Show the dialog in order to change the PIN associated with a running daemon.
 *
 * @return {void} Nothing.
 */
remoting.HostSetupDialog.prototype.showForPin = function() {
  this.usageStats_.hidden = true;
  this.startNewFlow_(
      [remoting.HostSetupFlow.State.ASK_PIN,
       remoting.HostSetupFlow.State.UPDATING_PIN,
       remoting.HostSetupFlow.State.UPDATED_PIN]);
};

/**
 * Show the dialog in order to stop the daemon.
 *
 * @return {void} Nothing.
 */
remoting.HostSetupDialog.prototype.showForStop = function() {
  // TODO(sergeyu): Add another step to unregister the host, crubg.com/121146 .
  this.startNewFlow_(
      [remoting.HostSetupFlow.State.STOPPING_HOST,
       remoting.HostSetupFlow.State.HOST_STOPPED]);
};

/**
 * @return {void} Nothing.
 */
remoting.HostSetupDialog.prototype.hide = function() {
  remoting.setMode(remoting.AppMode.HOME);
};

/**
 * Starts new flow with the specified sequence of steps.
 * @param {Array.<remoting.HostSetupFlow.State>} sequence Sequence of steps.
 * @private
 */
remoting.HostSetupDialog.prototype.startNewFlow_ = function(sequence) {
  this.flow_ = new remoting.HostSetupFlow(sequence);
  this.pinEntry_.value = '';
  this.pinConfirm_.value = '';
  this.pinErrorDiv_.hidden = true;
  this.updateState_();
};

/**
 * Updates current UI mode according to the current state of the setup
 * flow and start the action corresponding to the current step (if
 * any).
 * @private
 */
remoting.HostSetupDialog.prototype.updateState_ = function() {
  remoting.updateLocalHostState();

  /** @param {string} tag1
   *  @param {string=} opt_tag2 */
  function showDoneMessage(tag1, opt_tag2) {
    var messageDiv = document.getElementById('host-setup-done-message');
    l10n.localizeElementFromTag(messageDiv, tag1);
    messageDiv = document.getElementById('host-setup-done-message-2');
    if (opt_tag2) {
      l10n.localizeElementFromTag(messageDiv, opt_tag2);
    } else {
      messageDiv.innerText = '';
    }
    remoting.setMode(remoting.AppMode.HOST_SETUP_DONE);
  }
  /** @param {string} tag */
  function showErrorMessage(tag) {
    var errorDiv = document.getElementById('host-setup-error-message');
    l10n.localizeElementFromTag(errorDiv, tag);
    remoting.setMode(remoting.AppMode.HOST_SETUP_ERROR);
  }

  var state = this.flow_.getState();
  if (state == remoting.HostSetupFlow.State.NONE) {
    this.hide();
  } else if (state == remoting.HostSetupFlow.State.ASK_PIN) {
    remoting.setMode(remoting.AppMode.HOST_SETUP_ASK_PIN);
  } else if (state == remoting.HostSetupFlow.State.INSTALL_HOST) {
    this.installHost_();
  } else if (state == remoting.HostSetupFlow.State.STARTING_HOST) {
    remoting.showSetupProcessingMessage(/*i18n-content*/'HOST_SETUP_STARTING');
    this.startHost_();
  } else if (state == remoting.HostSetupFlow.State.UPDATING_PIN) {
    remoting.showSetupProcessingMessage(
        /*i18n-content*/'HOST_SETUP_UPDATING_PIN');
    this.updatePin_();
  } else if (state == remoting.HostSetupFlow.State.STOPPING_HOST) {
    remoting.showSetupProcessingMessage(/*i18n-content*/'HOST_SETUP_STOPPING');
    this.stopHost_();
  } else if (state == remoting.HostSetupFlow.State.HOST_STARTED) {
    // TODO(jamiewalch): Only display the second string if the computer's power
    // management settings indicate that it's necessary.
    showDoneMessage(/*i18n-content*/'HOST_SETUP_STARTED',
                    /*i18n-content*/'HOST_SETUP_STARTED_DISABLE_SLEEP');
  } else if (state == remoting.HostSetupFlow.State.UPDATED_PIN) {
    showDoneMessage(/*i18n-content*/'HOST_SETUP_UPDATED_PIN');
  } else if (state == remoting.HostSetupFlow.State.HOST_STOPPED) {
    showDoneMessage(/*i18n-content*/'HOST_SETUP_STOPPED');
  } else if (state == remoting.HostSetupFlow.State.REGISTRATION_FAILED) {
    showErrorMessage(/*i18n-content*/'ERROR_HOST_REGISTRATION_FAILED');
  } else if (state == remoting.HostSetupFlow.State.START_HOST_FAILED) {
    showErrorMessage(/*i18n-content*/'HOST_SETUP_HOST_FAILED');
  } else if (state == remoting.HostSetupFlow.State.UPDATE_PIN_FAILED) {
    showErrorMessage(/*i18n-content*/'HOST_SETUP_UPDATE_PIN_FAILED');
  } else if (state == remoting.HostSetupFlow.State.STOP_HOST_FAILED) {
    showErrorMessage(/*i18n-content*/'HOST_SETUP_STOP_FAILED');
  }
};

/**
 * Shows the prompt that asks the user to install the host.
 */
remoting.HostSetupDialog.prototype.installHost_ = function() {
  /** @type {remoting.HostSetupDialog} */
  var that = this;
  /** @type {remoting.HostSetupFlow} */
  var flow = this.flow_;

  /** @param {remoting.Error} error */
  var onError = function(error) {
    flow.switchToErrorState(error);
    that.updateState_();
  };

  var onDone = function() {
    that.hostController_.getLocalHostState(onHostState);
  };

  /** @param {remoting.HostController.State} state */
  var onHostState = function(state) {
    var installed =
        state != remoting.HostController.State.NOT_INSTALLED &&
        state != remoting.HostController.State.INSTALLING;

    if (installed) {
      that.flow_.switchToNextStep();
      that.updateState_();
    } else {
      // Prompt the user again if the host is not installed.
      hostInstallDialog.tryAgain();
    }
  };

  /** @type {remoting.HostInstallDialog} */
  var hostInstallDialog = new remoting.HostInstallDialog();
  hostInstallDialog.show(onDone, onError);
}

/**
 * Registers and starts the host.
 */
remoting.HostSetupDialog.prototype.startHost_ = function() {
  /** @type {remoting.HostSetupDialog} */
  var that = this;
  /** @type {remoting.HostSetupFlow} */
  var flow = this.flow_;

  /** @return {boolean} */
  function isFlowActive() {
    if (flow !== that.flow_ ||
        flow.getState() != remoting.HostSetupFlow.State.STARTING_HOST) {
      console.error('Host setup was interrupted when starting the host');
      return false;
    }
    return true;
  }

  function onHostStarted() {
    if (isFlowActive()) {
      flow.switchToNextStep();
      that.updateState_();
    }
  }

  /** @param {remoting.Error} error */
  function onError(error) {
    if (isFlowActive()) {
      flow.switchToErrorState(error);
      that.updateState_();
    }
  }

  this.hostController_.start(this.flow_.pin, this.flow_.consent, onHostStarted,
                             onError);
};

remoting.HostSetupDialog.prototype.updatePin_ = function() {
  /** @type {remoting.HostSetupDialog} */
  var that = this;
  /** @type {remoting.HostSetupFlow} */
  var flow = this.flow_;

  /** @return {boolean} */
  function isFlowActive() {
    if (flow !== that.flow_ ||
        flow.getState() != remoting.HostSetupFlow.State.UPDATING_PIN) {
      console.error('Host setup was interrupted when updating PIN');
      return false;
    }
    return true;
  }

  function onPinUpdated() {
    if (isFlowActive()) {
      flow.switchToNextStep();
      that.updateState_();
    }
  }

  /** @param {remoting.Error} error */
  function onError(error) {
    if (isFlowActive()) {
      flow.switchToErrorState(error);
      that.updateState_();
    }
  }

  this.hostController_.updatePin(flow.pin, onPinUpdated, onError);
};

/**
 * Stops the host.
 */
remoting.HostSetupDialog.prototype.stopHost_ = function() {
  /** @type {remoting.HostSetupDialog} */
  var that = this;
  /** @type {remoting.HostSetupFlow} */
  var flow = this.flow_;

  /** @return {boolean} */
  function isFlowActive() {
    if (flow !== that.flow_ ||
        flow.getState() != remoting.HostSetupFlow.State.STOPPING_HOST) {
      console.error('Host setup was interrupted when stopping the host');
      return false;
    }
    return true;
  }

  function onHostStopped() {
    if (isFlowActive()) {
      flow.switchToNextStep();
      that.updateState_();
    }
  }

  /** @param {remoting.Error} error */
  function onError(error) {
    if (isFlowActive()) {
      flow.switchToErrorState(error);
      that.updateState_();
    }
  }

  this.hostController_.stop(onHostStopped, onError);
};

/**
 * Validates the PIN and shows an error message if it's invalid.
 * @return {boolean} true if the PIN is valid, false otherwise.
 * @private
 */
remoting.HostSetupDialog.prototype.validatePin_ = function() {
  var pin = this.pinEntry_.value;
  var pinIsValid = remoting.HostSetupDialog.validPin_(pin);
  if (!pinIsValid) {
    l10n.localizeElementFromTag(
        this.pinErrorMessage_, /*i18n-content*/'INVALID_PIN');
  }
  this.pinErrorDiv_.hidden = pinIsValid;
  return pinIsValid;
};

/** @private */
remoting.HostSetupDialog.prototype.onPinSubmit_ = function() {
  if (this.flow_.getState() != remoting.HostSetupFlow.State.ASK_PIN) {
    console.error('PIN submitted in an invalid state', this.flow_.getState());
    return;
  }
  var pin1 = this.pinEntry_.value;
  var pin2 = this.pinConfirm_.value;
  if (pin1 != pin2) {
    l10n.localizeElementFromTag(
        this.pinErrorMessage_, /*i18n-content*/'PINS_NOT_EQUAL');
    this.pinErrorDiv_.hidden = false;
    this.prepareForPinEntry_();
    return;
  }
  if (!this.validatePin_()) {
    this.prepareForPinEntry_();
    return;
  }
  this.flow_.pin = pin1;
  this.flow_.consent = !this.usageStats_.hidden &&
      this.usageStatsCheckbox_.checked;
  this.flow_.switchToNextStep();
  this.updateState_();
};

/** @private */
remoting.HostSetupDialog.prototype.prepareForPinEntry_ = function() {
  this.pinEntry_.value = '';
  this.pinConfirm_.value = '';
  this.pinEntry_.focus();
};

/**
 * Returns whether a PIN is valid.
 *
 * @private
 * @param {string} pin A PIN.
 * @return {boolean} Whether the PIN is valid.
 */
remoting.HostSetupDialog.validPin_ = function(pin) {
  if (pin.length < 6) {
    return false;
  }
  for (var i = 0; i < pin.length; i++) {
    var c = pin.charAt(i);
    if ((c < '0') || (c > '9')) {
      return false;
    }
  }
  return true;
};

/** @type {remoting.HostSetupDialog} */
remoting.hostSetupDialog = null;
