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

/**
 * @fileoverview
 * Functions related to the 'client screen' for Chromoting.
 */

'use strict';

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

/**
 * @type {remoting.SessionConnector} The connector object, set when a connection
 *     is initiated.
 */
remoting.connector = null;

/**
 * @type {remoting.ClientSession} The client session object, set once the
 *     connector has invoked its onOk callback.
 */
remoting.clientSession = null;

/**
 * Initiate an IT2Me connection.
 */
remoting.connectIT2Me = function() {
  if (!remoting.connector) {
    remoting.connector = new remoting.SessionConnector(
        document.getElementById('session-mode'),
        remoting.onConnected,
        showConnectError_);
  }
  var accessCode = document.getElementById('access-code-entry').value;
  remoting.setMode(remoting.AppMode.CLIENT_CONNECTING);
  remoting.connector.connectIT2Me(accessCode);
};

/**
 * Update the remoting client layout in response to a resize event.
 *
 * @return {void} Nothing.
 */
remoting.onResize = function() {
  if (remoting.clientSession) {
    remoting.clientSession.onResize();
  }
};

/**
 * Handle changes in the visibility of the window, for example by pausing video.
 *
 * @return {void} Nothing.
 */
remoting.onVisibilityChanged = function() {
  if (remoting.clientSession) {
    remoting.clientSession.pauseVideo(
      ('hidden' in document) ? document.hidden : document.webkitHidden);
  }
}

/**
 * Disconnect the remoting client.
 *
 * @return {void} Nothing.
 */
remoting.disconnect = function() {
  if (!remoting.clientSession) {
    return;
  }
  if (remoting.clientSession.getMode() == remoting.ClientSession.Mode.IT2ME) {
    remoting.setMode(remoting.AppMode.CLIENT_SESSION_FINISHED_IT2ME);
  } else {
    remoting.setMode(remoting.AppMode.CLIENT_SESSION_FINISHED_ME2ME);
  }
  remoting.clientSession.disconnect(true);
  remoting.clientSession = null;
  console.log('Disconnected.');
};

/**
 * Sends a Ctrl-Alt-Del sequence to the remoting client.
 *
 * @return {void} Nothing.
 */
remoting.sendCtrlAltDel = function() {
  if (remoting.clientSession) {
    console.log('Sending Ctrl-Alt-Del.');
    remoting.clientSession.sendCtrlAltDel();
  }
};

/**
 * Sends a Print Screen keypress to the remoting client.
 *
 * @return {void} Nothing.
 */
remoting.sendPrintScreen = function() {
  if (remoting.clientSession) {
    console.log('Sending Print Screen.');
    remoting.clientSession.sendPrintScreen();
  }
};

/**
 * Callback function called when the state of the client plugin changes. The
 * current state is available via the |state| member variable.
 *
 * @param {number} oldState The previous state of the plugin.
 * @param {number} newState The current state of the plugin.
 */
function onClientStateChange_(oldState, newState) {
  switch (newState) {
    case remoting.ClientSession.State.CLOSED:
      console.log('Connection closed by host');
      if (remoting.clientSession.getMode() ==
          remoting.ClientSession.Mode.IT2ME) {
        remoting.setMode(remoting.AppMode.CLIENT_SESSION_FINISHED_IT2ME);
      } else {
        remoting.setMode(remoting.AppMode.CLIENT_SESSION_FINISHED_ME2ME);
      }
      break;

    case remoting.ClientSession.State.FAILED:
      var error = remoting.clientSession.getError();
      console.error('Client plugin reported connection failed: ' + error);
      if (error == null) {
        error = remoting.Error.UNEXPECTED;
      }
      showConnectError_(error);
      break;

    default:
      console.error('Unexpected client plugin state: ' + newState);
      // This should only happen if the web-app and client plugin get out of
      // sync, so MISSING_PLUGIN is a suitable error.
      showConnectError_(remoting.Error.MISSING_PLUGIN);
      break;
  }
  remoting.clientSession.disconnect(false);
  remoting.clientSession.removePlugin();
  remoting.clientSession = null;
}

/**
 * Show a client-side error message.
 *
 * @param {remoting.Error} errorTag The error to be localized and
 *     displayed.
 * @return {void} Nothing.
 */
function showConnectError_(errorTag) {
  console.error('Connection failed: ' + errorTag);
  var errorDiv = document.getElementById('connect-error-message');
  l10n.localizeElementFromTag(errorDiv, /** @type {string} */ (errorTag));
  remoting.accessCode = '';
  var mode = remoting.clientSession ? remoting.clientSession.getMode()
                                    : remoting.connector.getConnectionMode();
  if (mode == remoting.ClientSession.Mode.IT2ME) {
    remoting.setMode(remoting.AppMode.CLIENT_CONNECT_FAILED_IT2ME);
  } else {
    remoting.setMode(remoting.AppMode.CLIENT_CONNECT_FAILED_ME2ME);
  }
}

/**
 * Set the text on the buttons shown under the error message so that they are
 * easy to understand in the case where a successful connection failed, as
 * opposed to the case where a connection never succeeded.
 */
function setConnectionInterruptedButtonsText_() {
  var button1 = document.getElementById('client-reconnect-button');
  l10n.localizeElementFromTag(button1, /*i18n-content*/'RECONNECT');
  button1.removeAttribute('autofocus');
  var button2 = document.getElementById('client-finished-me2me-button');
  l10n.localizeElementFromTag(button2, /*i18n-content*/'OK');
  button2.setAttribute('autofocus', 'autofocus');
}

/**
 * Timer callback to update the statistics panel.
 */
function updateStatistics_() {
  if (!remoting.clientSession ||
      remoting.clientSession.getState() !=
      remoting.ClientSession.State.CONNECTED) {
    return;
  }
  var perfstats = remoting.clientSession.getPerfStats();
  remoting.stats.update(perfstats);
  remoting.clientSession.logStatistics(perfstats);
  // Update the stats once per second.
  window.setTimeout(updateStatistics_, 1000);
}

/**
 * Entry-point for Me2Me connections, handling showing of the host-upgrade nag
 * dialog if necessary.
 *
 * @param {string} hostId The unique id of the host.
 * @return {void} Nothing.
 */
remoting.connectMe2Me = function(hostId) {
  var host = remoting.hostList.getHostForId(hostId);
  if (!host) {
    showConnectError_(remoting.Error.HOST_IS_OFFLINE);
    return;
  }
  var webappVersion = chrome.runtime.getManifest().version;
  if (remoting.Host.needsUpdate(host, webappVersion)) {
    var needsUpdateMessage =
        document.getElementById('host-needs-update-message');
    l10n.localizeElementFromTag(needsUpdateMessage,
                                /*i18n-content*/'HOST_NEEDS_UPDATE_TITLE',
                                host.hostName);
    /** @type {Element} */
    var connect = document.getElementById('host-needs-update-connect-button');
    /** @type {Element} */
    var cancel = document.getElementById('host-needs-update-cancel-button');
    /** @param {Event} event */
    var onClick = function(event) {
      connect.removeEventListener('click', onClick, false);
      cancel.removeEventListener('click', onClick, false);
      if (event.target == connect) {
        remoting.connectMe2MeHostVersionAcknowledged_(host);
      } else {
        remoting.setMode(remoting.AppMode.HOME);
      }
    }
    connect.addEventListener('click', onClick, false);
    cancel.addEventListener('click', onClick, false);
    remoting.setMode(remoting.AppMode.CLIENT_HOST_NEEDS_UPGRADE);
  } else {
    remoting.connectMe2MeHostVersionAcknowledged_(host);
  }
};

/**
 * Shows PIN entry screen localized to include the host name, and registers
 * a host-specific one-shot event handler for the form submission.
 *
 * @param {remoting.Host} host The Me2Me host to which to connect.
 * @return {void} Nothing.
 */
remoting.connectMe2MeHostVersionAcknowledged_ = function(host) {
  if (!remoting.connector) {
    remoting.connector = new remoting.SessionConnector(
        document.getElementById('session-mode'),
        remoting.onConnected,
        showConnectError_);
  }
  remoting.setMode(remoting.AppMode.CLIENT_CONNECTING);

  /**
   * @param {string} tokenUrl Token-issue URL received from the host.
   * @param {string} scope OAuth scope to request the token for.
   * @param {string} hostPublicKey Host public key (DER and Base64 encoded).
   * @param {function(string, string):void} onThirdPartyTokenFetched Callback.
   */
  var fetchThirdPartyToken = function(
      tokenUrl, hostPublicKey, scope, onThirdPartyTokenFetched) {
    var thirdPartyTokenFetcher = new remoting.ThirdPartyTokenFetcher(
        tokenUrl, hostPublicKey, scope, host.tokenUrlPatterns,
        onThirdPartyTokenFetched);
    thirdPartyTokenFetcher.fetchToken();
  };

  /**
   * @param {boolean} supportsPairing
   * @param {function(string):void} onPinFetched
   */
  var requestPin = function(supportsPairing, onPinFetched) {
    /** @type {Element} */
    var pinForm = document.getElementById('pin-form');
    /** @type {Element} */
    var pinCancel = document.getElementById('cancel-pin-entry-button');
    /** @type {Element} */
    var rememberPin = document.getElementById('remember-pin');
    /** @type {Element} */
    var rememberPinCheckbox = document.getElementById('remember-pin-checkbox');
    /**
     * Event handler for both the 'submit' and 'cancel' actions. Using
     * a single handler for both greatly simplifies the task of making
     * them one-shot. If separate handlers were used, each would have
     * to unregister both itself and the other.
     *
     * @param {Event} event The click or submit event.
     */
    var onSubmitOrCancel = function(event) {
      pinForm.removeEventListener('submit', onSubmitOrCancel, false);
      pinCancel.removeEventListener('click', onSubmitOrCancel, false);
      var pinField = document.getElementById('pin-entry');
      var pin = pinField.value;
      pinField.value = '';
      if (event.target == pinForm) {
        event.preventDefault();

        // Set the focus away from the password field. This has to be done
        // before the password field gets hidden, to work around a Blink
        // clipboard-handling bug - http://crbug.com/281523.
        document.getElementById('pin-connect-button').focus();

        remoting.setMode(remoting.AppMode.CLIENT_CONNECTING);
        onPinFetched(pin);
        if (/** @type {boolean} */(rememberPinCheckbox.checked)) {
          remoting.connector.pairingRequested = true;
        }
      } else {
        remoting.setMode(remoting.AppMode.HOME);
      }
    };
    pinForm.addEventListener('submit', onSubmitOrCancel, false);
    pinCancel.addEventListener('click', onSubmitOrCancel, false);
    rememberPin.hidden = !supportsPairing;
    rememberPinCheckbox.checked = false;
    var message = document.getElementById('pin-message');
    l10n.localizeElement(message, host.hostName);
    remoting.setMode(remoting.AppMode.CLIENT_PIN_PROMPT);
  };

  /** @param {Object} settings */
  var connectMe2MeHostSettingsRetrieved = function(settings) {
    /** @type {string} */
    var clientId = '';
    /** @type {string} */
    var sharedSecret = '';
    var pairingInfo = /** @type {Object} */ (settings['pairingInfo']);
    if (pairingInfo) {
      clientId = /** @type {string} */ (pairingInfo['clientId']);
      sharedSecret = /** @type {string} */ (pairingInfo['sharedSecret']);
    }
    remoting.connector.connectMe2Me(host, requestPin, fetchThirdPartyToken,
                                    clientId, sharedSecret);
  }

  remoting.HostSettings.load(host.hostId, connectMe2MeHostSettingsRetrieved);
};

/** @param {remoting.ClientSession} clientSession */
remoting.onConnected = function(clientSession) {
  remoting.clientSession = clientSession;
  remoting.clientSession.setOnStateChange(onClientStateChange_);
  setConnectionInterruptedButtonsText_();
  var connectedTo = document.getElementById('connected-to');
  connectedTo.innerText = remoting.connector.getHostDisplayName();
  document.getElementById('access-code-entry').value = '';
  remoting.setMode(remoting.AppMode.IN_SESSION);
  remoting.toolbar.center();
  remoting.toolbar.preview();
  remoting.clipboard.startSession();
  updateStatistics_();
  if (remoting.connector.pairingRequested) {
    /**
     * @param {string} clientId
     * @param {string} sharedSecret
     */
    var onPairingComplete = function(clientId, sharedSecret) {
      var pairingInfo = {
        pairingInfo: {
          clientId: clientId,
          sharedSecret: sharedSecret
        }
      };
      remoting.HostSettings.save(remoting.connector.getHostId(), pairingInfo);
      remoting.connector.updatePairingInfo(clientId, sharedSecret);
    };
    // Use the platform name as a proxy for the local computer name.
    // TODO(jamiewalch): Use a descriptive name for the local computer, for
    // example, its Chrome Sync name.
    var clientName = '';
    if (navigator.platform.indexOf('Mac') != -1) {
      clientName = 'Mac';
    } else if (navigator.platform.indexOf('Win32') != -1) {
      clientName = 'Windows';
    } else if (navigator.userAgent.match(/\bCrOS\b/)) {
      clientName = 'ChromeOS';
    } else if (navigator.platform.indexOf('Linux') != -1) {
      clientName = 'Linux';
    } else {
      console.log('Unrecognized client platform. Using navigator.platform.');
      clientName = navigator.platform;
    }
    clientSession.requestPairing(clientName, onPairingComplete);
  }
};
