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

// require: cr.js
// require: cr/ui.js
// require: cr/ui/tree.js

(function() {
  /**
   * A helper function to determine if a node is the root of its type.
   *
   * @param {!Object} node The node to check.
   */
  var isTypeRootNode = function(node) {
    return node.PARENT_ID == 'r' && node.UNIQUE_SERVER_TAG != '';
  }

  /**
   * A helper function to determine if a node is a child of the given parent.
   *
   * @param {string} parentId The ID of the parent.
   * @param {!Object} node The node to check.
   */
  var isChildOf = function(parentId, node) {
    return node.PARENT_ID == parentId;
  }

  /**
   * A helper function to sort sync nodes.
   *
   * Sorts by position index if possible, falls back to sorting by name, and
   * finally sorting by METAHANDLE.
   *
   * If this proves to be slow and expensive, we should experiment with moving
   * this functionality to C++ instead.
   */
  var nodeComparator = function(nodeA, nodeB) {
    if (nodeA.hasOwnProperty('positionIndex') &&
        nodeB.hasOwnProperty('positionIndex')) {
      return nodeA.positionIndex - nodeB.positionIndex;
    } else if (nodeA.NON_UNIQUE_NAME != nodeB.NON_UNIQUE_NAME) {
      return nodeA.NON_UNIQUE_NAME.localeCompare(nodeB.NON_UNIQUE_NAME);
    } else {
      return nodeA.METAHANDLE - nodeB.METAHANDLE;
    }
  }

  /**
   * Updates the node detail view with the details for the given node.
   * @param {!Object} node The struct representing the node we want to display.
   */
  function updateNodeDetailView(node) {
    var nodeDetailsView = $('node-details');
    nodeDetailsView.hidden = false;
    jstProcess(new JsEvalContext(node.entry_), nodeDetailsView);
  }

  /**
   * Updates the 'Last refresh time' display.
   * @param {string} The text to display.
   */
  function setLastRefreshTime(str) {
    $('node-browser-refresh-time').textContent = str;
  }

  /**
   * Creates a new sync node tree item.
   *
   * @constructor
   * @param {!Object} node The nodeDetails object for the node as returned by
   *     chrome.sync.getAllNodes().
   * @extends {cr.ui.TreeItem}
   */
  var SyncNodeTreeItem = function(node) {
    var treeItem = new cr.ui.TreeItem();
    treeItem.__proto__ = SyncNodeTreeItem.prototype;

    treeItem.entry_ = node;
    treeItem.label = node.NON_UNIQUE_NAME;
    if (node.IS_DIR) {
      treeItem.mayHaveChildren_ = true;

      // Load children on expand.
      treeItem.expanded_ = false;
      treeItem.addEventListener('expand',
                                treeItem.handleExpand_.bind(treeItem));
    } else {
      treeItem.classList.add('leaf');
    }
    return treeItem;
  };

  SyncNodeTreeItem.prototype = {
    __proto__: cr.ui.TreeItem.prototype,

    /**
     * Finds the children of this node and appends them to the tree.
     */
    handleExpand_: function(event) {
      var treeItem = this;

      if (treeItem.expanded_) {
        return;
      }
      treeItem.expanded_ = true;

      var children = treeItem.tree.allNodes.filter(
          isChildOf.bind(undefined, treeItem.entry_.ID));
      children.sort(nodeComparator);

      children.forEach(function(node) {
        treeItem.add(new SyncNodeTreeItem(node));
      });
    },
  };

  /**
   * Creates a new sync node tree.  Technically, it's a forest since it each
   * type has its own root node for its own tree, but it still looks and acts
   * mostly like a tree.
   *
   * @param {Object=} opt_propertyBag Optional properties.
   * @constructor
   * @extends {cr.ui.Tree}
   */
  var SyncNodeTree = cr.ui.define('tree');

  SyncNodeTree.prototype = {
    __proto__: cr.ui.Tree.prototype,

    decorate: function() {
      cr.ui.Tree.prototype.decorate.call(this);
      this.addEventListener('change', this.handleChange_.bind(this));
      this.allNodes = [];
    },

    populate: function(nodes) {
      var tree = this;

      // We store the full set of nodes in the SyncNodeTree object.
      tree.allNodes = nodes;

      var roots = tree.allNodes.filter(isTypeRootNode);
      roots.sort(nodeComparator);

      roots.forEach(function(typeRoot) {
        tree.add(new SyncNodeTreeItem(typeRoot));
      });
    },

    handleChange_: function(event) {
      if (this.selectedItem) {
        updateNodeDetailView(this.selectedItem);
      }
    }
  };

  /**
   * Clears any existing UI state.  Useful prior to a refresh.
   */
  function clear() {
    var treeContainer = $('sync-node-tree-container');
    while (treeContainer.firstChild) {
      treeContainer.removeChild(treeContainer.firstChild);
    }

    var nodeDetailsView = $('node-details');
    nodeDetailsView.hidden = true;
  }

  /**
   * Fetch the latest set of nodes and refresh the UI.
   */
  function refresh() {
    $('node-browser-refresh-button').disabled = true;

    clear();
    setLastRefreshTime('In progress since ' + (new Date()).toLocaleString());

    chrome.sync.getAllNodes(function(nodeMap) {
      // Put all nodes into one big list that ignores the type.
      var nodes = nodeMap.
          map(function(x) { return x.nodes; }).
          reduce(function(a, b) { return a.concat(b); });

      var treeContainer = $('sync-node-tree-container');
      var tree = document.createElement('tree');
      tree.setAttribute('id', 'sync-node-tree');
      tree.setAttribute('icon-visibility', 'parent');
      treeContainer.appendChild(tree);

      cr.ui.decorate(tree, SyncNodeTree);
      tree.populate(nodes);

      setLastRefreshTime((new Date()).toLocaleString());
      $('node-browser-refresh-button').disabled = false;
    });
  }

  document.addEventListener('DOMContentLoaded', function(e) {
    $('node-browser-refresh-button').addEventListener('click', refresh);
    cr.ui.decorate('#sync-node-splitter', cr.ui.Splitter);

    // Automatically trigger a refresh the first time this tab is selected.
    $('sync-browser-tab').addEventListener('selectedChange', function f(e) {
      if (this.selected) {
        $('sync-browser-tab').removeEventListener('selectedChange', f);
        refresh();
      }
    });
  });

})();
