// 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
 * Class representing an entry in the host-list portion of the home screen.
 */

'use strict';

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

/**
 * An entry in the host table.
 * @param {remoting.Host} host The host, as obtained from Apiary.
 * @param {number} webappMajorVersion The major version nmber of the web-app,
 *     used to identify out-of-date hosts.
 * @param {function(remoting.HostTableEntry):void} onRename Callback for
 *     rename operations.
 * @param {function(remoting.HostTableEntry):void=} opt_onDelete Callback for
 *     delete operations.
 * @constructor
 */
remoting.HostTableEntry = function(
    host, webappMajorVersion, onRename, opt_onDelete) {
  /** @type {remoting.Host} */
  this.host = host;
  /** @type {number} */
  this.webappMajorVersion_ = webappMajorVersion;
  /** @type {function(remoting.HostTableEntry):void} @private */
  this.onRename_ = onRename;
  /** @type {undefined|function(remoting.HostTableEntry):void} @private */
  this.onDelete_ = opt_onDelete;

  /** @type {HTMLElement} */
  this.tableRow = null;
  /** @type {HTMLElement} @private */
  this.hostNameCell_ = null;
  /** @type {HTMLElement} @private */
  this.warningOverlay_ = null;
  // References to event handlers so that they can be removed.
  /** @type {function():void} @private */
  this.onBlurReference_ = function() {};
  /** @type {function():void} @private */
  this.onConfirmDeleteReference_ = function() {};
  /** @type {function():void} @private */
  this.onCancelDeleteReference_ = function() {};
  /** @type {function():void?} @private */
  this.onConnectReference_ = null;
};

/**
 * Create the HTML elements for this entry and set up event handlers.
 * @return {void} Nothing.
 */
remoting.HostTableEntry.prototype.createDom = function() {
  // Create the top-level <div>
  var tableRow = /** @type {HTMLElement} */ document.createElement('div');
  tableRow.classList.add('section-row');
  // Create the host icon cell.
  var hostIconDiv = /** @type {HTMLElement} */ document.createElement('div');
  hostIconDiv.classList.add('host-list-main-icon');
  var warningOverlay =
      /** @type {HTMLElement} */ document.createElement('span');
  hostIconDiv.appendChild(warningOverlay);
  var hostIcon = /** @type {HTMLElement} */ document.createElement('img');
  hostIcon.src = 'icon_host.webp';
  hostIconDiv.appendChild(hostIcon);
  tableRow.appendChild(hostIconDiv);
  // Create the host name cell.
  var hostNameCell = /** @type {HTMLElement} */ document.createElement('div');
  hostNameCell.classList.add('box-spacer');
  hostNameCell.id = 'host_' + this.host.hostId;
  tableRow.appendChild(hostNameCell);
  // Create the host rename cell.
  var editButton = /** @type {HTMLElement} */ document.createElement('span');
  var editButtonImg = /** @type {HTMLElement} */ document.createElement('img');
  editButtonImg.title = chrome.i18n.getMessage(
      /*i18n-content*/'TOOLTIP_RENAME');
  editButtonImg.src = 'icon_pencil.webp';
  editButton.tabIndex = 0;
  editButton.classList.add('clickable');
  editButton.classList.add('host-list-edit');
  editButtonImg.classList.add('host-list-rename-icon');
  editButton.appendChild(editButtonImg);
  tableRow.appendChild(editButton);
  // Create the host delete cell.
  var deleteButton = /** @type {HTMLElement} */ document.createElement('span');
  var deleteButtonImg =
      /** @type {HTMLElement} */ document.createElement('img');
  deleteButtonImg.title =
      chrome.i18n.getMessage(/*i18n-content*/'TOOLTIP_DELETE');
  deleteButtonImg.src = 'icon_cross.webp';
  deleteButton.tabIndex = 0;
  deleteButton.classList.add('clickable');
  deleteButton.classList.add('host-list-edit');
  deleteButtonImg.classList.add('host-list-remove-icon');
  deleteButton.appendChild(deleteButtonImg);
  tableRow.appendChild(deleteButton);

  this.init(tableRow, warningOverlay, hostNameCell, editButton, deleteButton);
};

/**
 * Associate the table row with the specified elements and callbacks, and set
 * up event handlers.
 *
 * @param {HTMLElement} tableRow The top-level <div> for the table entry.
 * @param {HTMLElement} warningOverlay The <span> element to render a warning
 *     icon on top of the host icon.
 * @param {HTMLElement} hostNameCell The element containing the host name.
 * @param {HTMLElement} editButton The <img> containing the pencil icon for
 *     editing the host name.
 * @param {HTMLElement=} opt_deleteButton The <img> containing the cross icon
 *     for deleting the host, if present.
 * @return {void} Nothing.
 */
remoting.HostTableEntry.prototype.init = function(
    tableRow, warningOverlay, hostNameCell, editButton, opt_deleteButton) {
  this.tableRow = tableRow;
  this.warningOverlay_ = warningOverlay;
  this.hostNameCell_ = hostNameCell;
  this.setHostName_();

  /** @type {remoting.HostTableEntry} */
  var that = this;

  /** @param {Event} event The click event. */
  var beginRename = function(event) {
    that.beginRename_();
    event.stopPropagation();
  };
  /** @param {Event} event The keyup event. */
  var beginRenameKeyboard = function(event) {
    if (event.which == 13 || event.which == 32) {
      that.beginRename_();
      event.stopPropagation();
    }
  };
  editButton.addEventListener('click', beginRename, true);
  editButton.addEventListener('keyup', beginRenameKeyboard, true);
  this.registerFocusHandlers_(editButton);

  if (opt_deleteButton) {
    /** @param {Event} event The click event. */
    var confirmDelete = function(event) {
      that.showDeleteConfirmation_();
      event.stopPropagation();
    };
    /** @param {Event} event The keyup event. */
    var confirmDeleteKeyboard = function(event) {
      if (event.which == 13 || event.which == 32) {
        that.showDeleteConfirmation_();
      }
    };
    opt_deleteButton.addEventListener('click', confirmDelete, false);
    opt_deleteButton.addEventListener('keyup', confirmDeleteKeyboard, false);
    this.registerFocusHandlers_(opt_deleteButton);
  }
  this.updateStatus();
};

/**
 * Update the row to reflect the current status of the host (online/offline and
 * clickable/unclickable).
 *
 * @param {boolean=} opt_forEdit True if the status is being updated in order
 *     to allow the host name to be edited.
 * @return {void} Nothing.
 */
remoting.HostTableEntry.prototype.updateStatus = function(opt_forEdit) {
  var clickToConnect = this.host.status == 'ONLINE' && !opt_forEdit;
  if (clickToConnect) {
    if (!this.onConnectReference_) {
      /** @type {string} */
      var encodedHostId = encodeURIComponent(this.host.hostId)
      this.onConnectReference_ = function() {
        remoting.connectMe2Me(encodedHostId);
      };
      this.tableRow.addEventListener('click', this.onConnectReference_, false);
    }
    this.tableRow.classList.add('clickable');
    this.tableRow.title = chrome.i18n.getMessage(
        /*i18n-content*/'TOOLTIP_CONNECT', this.host.hostName);
  } else {
    if (this.onConnectReference_) {
      this.tableRow.removeEventListener('click', this.onConnectReference_,
                                        false);
      this.onConnectReference_ = null;
    }
    this.tableRow.classList.remove('clickable');
    this.tableRow.title = '';
  }
  var showOffline = this.host.status != 'ONLINE';
  if (showOffline) {
    this.tableRow.classList.remove('host-online');
    this.tableRow.classList.add('host-offline');
  } else {
    this.tableRow.classList.add('host-online');
    this.tableRow.classList.remove('host-offline');
  }
  this.warningOverlay_.hidden = !remoting.Host.needsUpdate(
      this.host, this.webappMajorVersion_);
};

/**
 * Prepare the host for renaming by replacing its name with an edit box.
 * @return {void} Nothing.
 * @private
 */
remoting.HostTableEntry.prototype.beginRename_ = function() {
  var editBox = /** @type {HTMLInputElement} */ document.createElement('input');
  editBox.type = 'text';
  editBox.value = this.host.hostName;
  this.hostNameCell_.innerText = '';
  this.hostNameCell_.appendChild(editBox);
  editBox.select();

  this.onBlurReference_ = this.commitRename_.bind(this);
  editBox.addEventListener('blur', this.onBlurReference_, false);

  editBox.addEventListener('keydown', this.onKeydown_.bind(this), false);
  this.updateStatus(true);
};

/**
 * Accept the hostname entered by the user.
 * @return {void} Nothing.
 * @private
 */
remoting.HostTableEntry.prototype.commitRename_ = function() {
  var editBox = this.hostNameCell_.querySelector('input');
  if (editBox) {
    if (this.host.hostName != editBox.value) {
      this.host.hostName = editBox.value;
      this.onRename_(this);
    }
    this.removeEditBox_();
  }
};

/**
 * Prompt the user to confirm or cancel deletion of a host.
 * @return {void} Nothing.
 * @private
 */
remoting.HostTableEntry.prototype.showDeleteConfirmation_ = function() {
  var message = document.getElementById('confirm-host-delete-message');
  l10n.localizeElement(message, this.host.hostName);
  var confirm = document.getElementById('confirm-host-delete');
  var cancel = document.getElementById('cancel-host-delete');
  this.onConfirmDeleteReference_ = this.confirmDelete_.bind(this);
  this.onCancelDeleteReference_ = this.cancelDelete_.bind(this);
  confirm.addEventListener('click', this.onConfirmDeleteReference_, false);
  cancel.addEventListener('click', this.onCancelDeleteReference_, false);
  remoting.setMode(remoting.AppMode.CONFIRM_HOST_DELETE);
};

/**
 * Confirm deletion of a host.
 * @return {void} Nothing.
 * @private
 */
remoting.HostTableEntry.prototype.confirmDelete_ = function() {
  this.onDelete_(this);
  this.cleanUpConfirmationEventListeners_();
  remoting.setMode(remoting.AppMode.HOME);
};

/**
 * Cancel deletion of a host.
 * @return {void} Nothing.
 * @private
 */
remoting.HostTableEntry.prototype.cancelDelete_ = function() {
  this.cleanUpConfirmationEventListeners_();
  remoting.setMode(remoting.AppMode.HOME);
};

/**
 * Remove the confirm and cancel event handlers, which refer to this object.
 * @return {void} Nothing.
 * @private
 */
remoting.HostTableEntry.prototype.cleanUpConfirmationEventListeners_ =
    function() {
  var confirm = document.getElementById('confirm-host-delete');
  var cancel = document.getElementById('cancel-host-delete');
  confirm.removeEventListener('click', this.onConfirmDeleteReference_, false);
  cancel.removeEventListener('click', this.onCancelDeleteReference_, false);
  this.onCancelDeleteReference_ = function() {};
  this.onConfirmDeleteReference_ = function() {};
};

/**
 * Remove the edit box corresponding to the specified host, and reset its name.
 * @return {void} Nothing.
 * @private
 */
remoting.HostTableEntry.prototype.removeEditBox_ = function() {
  var editBox = this.hostNameCell_.querySelector('input');
  if (editBox) {
    // onblur will fire when the edit box is removed, so remove the hook.
    editBox.removeEventListener('blur', this.onBlurReference_, false);
  }
  // Update the tool-top and event handler.
  this.updateStatus();
  this.setHostName_();
};

/**
 * Create the DOM nodes and event handlers for the hostname cell.
 * @return {void} Nothing.
 * @private
 */
remoting.HostTableEntry.prototype.setHostName_ = function() {
  var hostNameNode = /** @type {HTMLElement} */ document.createElement('a');
  if (this.host.status == 'ONLINE') {
    if (remoting.Host.needsUpdate(this.host, this.webappMajorVersion_)) {
      hostNameNode.innerText = chrome.i18n.getMessage(
          /*i18n-content*/'UPDATE_REQUIRED', this.host.hostName);
    } else {
      hostNameNode.innerText = this.host.hostName;
    }
    hostNameNode.href = '#';
    this.registerFocusHandlers_(hostNameNode);
    /** @type {remoting.HostTableEntry} */
    var that = this;
    /** @param {Event} event */
    var onKeyDown = function(event) {
      if (that.onConnectReference_ &&
          (event.which == 13 || event.which == 32)) {
        that.onConnectReference_();
      }
    };
    hostNameNode.addEventListener('keydown', onKeyDown, false);
  } else {
    if (this.host.updatedTime) {
      var lastOnline = new Date(this.host.updatedTime);
      var now = new Date();
      var displayString = '';
      if (now.getFullYear() == lastOnline.getFullYear() &&
          now.getMonth() == lastOnline.getMonth() &&
          now.getDate() == lastOnline.getDate()) {
        displayString = lastOnline.toLocaleTimeString();
      } else {
        displayString = lastOnline.toLocaleDateString();
      }
      hostNameNode.innerText = chrome.i18n.getMessage(
          /*i18n-content*/'LAST_ONLINE', [this.host.hostName, displayString]);
    } else {
      hostNameNode.innerText = chrome.i18n.getMessage(
          /*i18n-content*/'OFFLINE', this.host.hostName);
    }
  }
  hostNameNode.classList.add('host-list-label');
  this.hostNameCell_.innerText = '';  // Remove previous contents (if any).
  this.hostNameCell_.appendChild(hostNameNode);
};

/**
 * Handle a key event while the user is typing a host name
 * @param {Event} event The keyboard event.
 * @return {void} Nothing.
 * @private
 */
remoting.HostTableEntry.prototype.onKeydown_ = function(event) {
  if (event.which == 27) {  // Escape
    this.removeEditBox_();
  } else if (event.which == 13) {  // Enter
    this.commitRename_();
  }
};

/**
 * Register focus and blur handlers to cause the parent node to be highlighted
 * whenever a child link has keyboard focus. Note that this is only necessary
 * because Chrome does not yet support the draft CSS Selectors 4 specification
 * (http://www.w3.org/TR/selectors4/#subject), which provides a more elegant
 * solution to this problem.
 *
 * @param {HTMLElement} e The element on which to register the event handlers.
 * @return {void} Nothing.
 * @private
 */
remoting.HostTableEntry.prototype.registerFocusHandlers_ = function(e) {
  e.addEventListener('focus', this.onFocusChange_.bind(this), false);
  e.addEventListener('blur', this.onFocusChange_.bind(this), false);
};

/**
 * Handle a focus change event within this table row.
 * @return {void} Nothing.
 * @private
 */
remoting.HostTableEntry.prototype.onFocusChange_ = function() {
  var element = document.activeElement;
  while (element) {
    if (element == this.tableRow) {
      this.tableRow.classList.add('child-focused');
      return;
    }
    element = element.parentNode;
  }
  this.tableRow.classList.remove('child-focused');
};
