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


(function(exports) {
  /**
   * Orientation of a line.
   * @enum {boolean}
   */
  var Orientation = {
    VERTICAL: false,
    HORIZONTAL: true
  }

  /**
   * Map from keysetId to layout.
   * @type {Map<String,KeysetLayout>}
   * @private
   */
  var layouts = {};

  /**
   * Container for storing a keyset's layout.
   */
  var KeysetLayout = function() {
    this.keys = [];
  }

  KeysetLayout.prototype = {
    /**
     * All keys in the keyset.
     * @type {Array<Key>}
     */
    keys: undefined,

    /**
     * Spacial partitioning of all keys in the keyset.
     * @type {DecisionNode}
     */
    tree: undefined,

    /**
     * Add a key to the keyset.
     */
    add: function(key) {
      this.keys.push(key);
    },

    /**
     * Regenerates a decision tree using the keys in the keyset.
     */
    regenerateTree: function() {
      // Split using horizontal lines first, as keyboards tend to be
      // row-centric.
      var splits = findSplits(this.keys, Orientation.HORIZONTAL);
      this.tree = createBinaryTree(0, splits.length - 1, splits);
      if (this.tree)
        this.tree.populate(this.keys);
    },

    /**
     * Searches the tree for the key closest to the point provided.
     * @param {number} x The x-coordinate.
     * @param {number} y The y-coordinate.
     * @return {?kb-key} The key, or null if none found.
     */
    findClosestKey: function(x, y) {
      var closestNode = this.tree.findClosestNode(x, y);
      var key = closestNode.data;
      if (!key)
        return;
      // Ignore touches that aren't close.
      return key.distanceTo(x, y) <= MAX_TOUCH_FUZZ_DISTANCE ?
          key.key : null;
    },

    /**
     * Returns the position data of all keys in this keyset.
     * @return {Array<Map>}
     */
    getLayout: function() {
      return this.keys.map(function(key) {
        return key.toMap();
      });
    },
  };

  /**
   * Container for caching a key's data.
   * @param {{style: {left: number, top: number, width: number,
   *                  height: number}}} key The key to cache.
   *     left: The x-coordinate of the left edge of the key.
   *     top: The y-coordinate of the top edge of the key.
   *     width: The width of the key in px.
   *     height: The height of the key in px.
   * @constructor
   */
  var Key = function(key) {
    this.key = key;
    var style = key.style;
    this.top = parseFloat(style.top) - KEY_PADDING_TOP;
    this.left = parseFloat(style.left);
    this.right = this.left + parseFloat(style.width);
    this.bottom = this.top + parseFloat(style.height) + KEY_PADDING_TOP
        + KEY_PADDING_BOTTOM;
  }

  Key.prototype = {
    /**
     * Manhattan distance from the the provided point to the key.
     * @param {number} x The x-coordinate of the point.
     * @param {number} y The y-coordinate of the point.
     * @return {number}
     */
    distanceTo: function(x, y) {
      return Math.abs(this.intersect(new Line(x))) +
          Math.abs(this.intersect(new Line(y, true)));
    },

    /**
     * Checks whether the key intersects with the line provided.
     * @param {!Line} line The line.
     * @return {number} Zero if it intersects, signed manhattan distance if it
     *     does not.
     */
    intersect: function(line) {
      var min = line.rotated ? this.top : this.left;
      var max = line.rotated ? this.bottom : this.right;
      return (line.c > max) ? line.c - max : Math.min(0, line.c - min);
    },

    /**
     * Returns the Key as a map.
     * @return {Map<String,number>}
     */
    toMap: function() {
      return {
        'x': this.left,
        'y': this.top,
        'width': this.right - this.left,
        'height': this.bottom - this.bottom,
      }
    },
  };

  /**
   * Object representing the line y = c or x = c.
   * @param {number} c The x or y coordinate of the intersection line depending
   *     on orientation.
   * @param {Orientation} orientation The orientation of the line.
   * @constructor
   */
  var Line = function(c, orientation) {
    this.c = c;
    this.rotated = orientation;
  };

  Line.prototype = {
    /**
     * The position of the provided point in relation to the line.
     * @param {number} x The x-coordinate of the point.
     * @param {number} y The y-coordinate of the point.
     * @return {number} Zero if they intersect, negative if the point is before
     *    the line, positive if it's after.
     */
    testPoint: function(x, y) {
      var c = this.rotated ? y : x;
      return this.c == c ? 0 : c - this.c;
    },

    test: function(key) {
      // Key already provides an intersect method. If the key is to the right of
      // the line, then the line is to the left of the key.
      return -1 * key.intersect(this);
    },
  };

  /**
   * A node used to split 2D space.
   * @param {Line} line The line to split the space with.
   * @constructor
   */
  var DecisionNode = function(line) {
    this.decision = line;
  };

  DecisionNode.prototype = {
    /**
     * The test whether to proceed in the left or right branch.
     * @type {Line}
     */
    decision: undefined,

    /**
     * The branch for nodes that failed the decision test.
     * @type {?DecisionNode}
     */
    fail: undefined,

    /**
     * The branch for nodes that passed the decision test.
     * @type {?DecisionNode}
     */
    pass: undefined,

    /**
     * Finds the node closest to the point provided.
     * @param {number} x The x-coordinate.
     * @param {number} y The y-coordinate.
     * @return {DecisionNode | LeafNode}
     */
    findClosestNode: function(x, y) {
      return this.search(function(node) {
        return node.decision.testPoint(x, y) >= 0;
      });
    },

    /**
     * Populates the decision tree with elements.
     * @param {Array{Key}} The child elements.
     */
    populate: function(data) {
      if (!data.length)
        return;
      var pass = [];
      var fail = [];
      for (var i = 0; i < data.length; i++) {
        var result = this.decision.test(data[i]);
        // Add to both branches if result == 0.
        if (result >= 0)
          pass.push(data[i]);
        if (result <= 0)
          fail.push(data[i]);
      }
      var currentRotation = this.decision.rotated;
      /**
       * Splits the tree further such that each leaf has exactly one data point.
       * @param {Array} array The data points.
       * @return {DecisionNode | LeafNode} The new branch for the tree.
       */
      var updateBranch = function(array) {
        if (array.length == 1) {
          return new LeafNode(array[0]);
        } else {
          var splits = findSplits(array, !currentRotation);
          var tree = createBinaryTree(0, splits.length - 1, splits);
          tree.populate(array);
          return tree;
        }
      };
      // All elements that passed the decision test.
      if (pass.length > 0) {
        if (this.pass)
          this.pass.populate(pass);
        else
          this.pass = updateBranch(pass);
      }
      // All elements that failed the decision test.
      if (fail.length > 0) {
        if (this.fail)
          this.fail.populate(fail);
        else
          this.fail = updateBranch(fail);
      }
    },

    /**
     * Searches for the first leaf that matches the search function.
     * @param {Function<DecisionNode>: Boolean} searchFn The function used to
     *    determine whether to search in the left or right subtree.
     * @return {DecisionNode | LeafNode} The node that most closely matches the
     *    search parameters.
     */
    search: function(searchFn) {
      if (searchFn(this)) {
        return this.pass ? this.pass.search(searchFn) : this;
      }
      return this.fail ? this.fail.search(searchFn) : this;
    },

    /**
     * Tests whether the key belongs in the left or right branch of this node.
     * @param {Key} key The key being tested.
     * @return {boolean} Whether it belongs in the right branch.
     */
    test: function(key) {
      return this.decision.testKey(key);
    },
  };

  /**
   * Structure representing a leaf in the decision tree. It contains a single
   * data point.
   */
  var LeafNode = function(data) {
    this.data = data;
  };

  LeafNode.prototype = {
    search: function() {
      return this;
    },
  };

  /**
   * Converts the array to a binary tree.
   * @param {number} start The start index.
   * @param {number} end The end index.
   * @param {Array} nodes The array to convert.
   * @return {DecisionNode}
   */
  var createBinaryTree = function(start, end, nodes) {
    if (start > end)
      return;
    var midpoint = Math.floor((end + start)/2);
    var root = new DecisionNode(nodes[midpoint]);
    root.fail = createBinaryTree(start, midpoint - 1, nodes);
    root.pass = createBinaryTree(midpoint + 1, end, nodes);
    return root;
  };

  /**
   * Calculates the optimum split points on the specified axis.
   * @param {Array.<Keys>} allKeys All keys in the keyset.
   * @param {Orientation} orientation Whether to split on the y-axis instead.
   * @return {Array.<Line>} The optimum split points.
   */
  var findSplits = function(allKeys, orientation) {
    /**
     * Returns the minimum edge on the key.
     * @param {Key} key The key.
     * @return {number}
     */
    var getMin = function(key) {
      return orientation == Orientation.HORIZONTAL ? key.top : key.left;
    };

    /**
     * Returns the maximum edge on the key.
     * @param {Key} key The key.
     */
    var getMax = function(key) {
      return orientation == Orientation.HORIZONTAL ? key.bottom : key.right;
    };

    /**
     * Returns a duplicate free version of array.
     * @param {Array} array A sorted array.
     * @return {Array} Sorted array without duplicates.
     */
    var unique = function(array) {
      var result = [];
      for (var i = 0; i< array.length; i++) {
        if (i == 0 || result[result.length -1] != array[i])
            result.push(array[i]);
      }
      return result;
    };

    /**
     * Creates an array of zeroes.
     * @param {number} length The length of the array.
     * @return {Array{number}}
     */
    var zeroes = function(length) {
      var array = new Array(length);
      for (var i = 0; i < length; i++) {
        array[i] = 0;
      }
      return array;
    }
    // All edges of keys.
    var edges = [];
    for (var i = 0; i < allKeys.length; i++) {
      var key = allKeys[i];
      var min = getMin(key);
      var max = getMax(key);
      edges.push(min);
      edges.push(max);
    }
    // Array.sort() sorts lexicographically by default.
    edges.sort(function(a, b) {
      return a - b;
    });
    edges = unique(edges);
    // Container for projection sum from edge i to edge i + 1.
    var intervalWeight = zeroes(edges.length);

    for (var i = 0; i < allKeys.length; i++) {
      var key = allKeys[i];
      var min = getMin(key);
      var max = getMax(key);
      var index =
          exports.binarySearch(edges, 0, edges.length - 1, function(index) {
        var edge = edges[index];
        return edge == min ? 0 : min - edge;
      });
      if (index < 0 || min != edges[index]) {
        console.error("Unable to split keys.");
        return;
      }
      // Key can span multiple edges.
      for (var j = index; j < edges.length && edges[j] < max; j++) {
        intervalWeight[j] ++;
      }
    }

    var splits = [];
    // Min and max are bad splits.
    for (var i = 1; i < intervalWeight.length - 1; i++) {
      if (intervalWeight[i] < intervalWeight[i - 1]) {
        var mid = Math.abs((edges[i] + edges[i+1]) / 2)
        splits.push(new Line(mid, orientation));
      }
    }
    return splits;
  }

  /**
   * Caches the layout of current keysets.
   */
  function recordKeysets_() {
    layouts = {};
    var keysets = $('keyboard').querySelectorAll('kb-keyset').array();
    for (var i = 0; i < keysets.length; i++) {
      var keyset = keysets[i];
      var layout = new KeysetLayout();
      var rows = keyset.querySelectorAll('kb-row').array();
      for (var j = 0; j < rows.length; j++) {
        var row = rows[j];
        var nodes = row.children;
        for (var k = 0 ; k < nodes.length; k++) {
          layout.add(new Key(nodes[k]));
        }
      }
      layout.regenerateTree();
      layouts[keyset.id] = layout;
    }
  };

  /**
   * Returns the layout of the keyset.
   * @param{!String} id The id of the keyset.
   * @private
   */
  var getKeysetLayout_ = function(id) {
    return layouts[id];
  };

  exports.getKeysetLayout = getKeysetLayout_;
  exports.recordKeysets = recordKeysets_;
})(this);
