<!DOCTYPE html>
<!--
Copyright (c) 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.
-->
<link rel="import" href="/base/guid.html">
<script>
'use strict';

tr.exportTo('tr.b', function() {

  /**
   * KeyEventManager avoids leaks when listening for keys.
   *
   * A common but leaky pattern is:
   *   document.addEventListener('key*', function().bind(this))
   * This leaks.
   *
   * Instead do this:
   *   KeyEventManager.instance.addListener('keyDown', func, this);
   *
   * This will not leak. BUT, note, if "this" is not attached to the document,
   * it will NOT receive input events.
   *
   * Conceptually, KeyEventManager works by making the this refrence "weak",
   * which is actually accomplished by putting a guid on the thisArg. When keys
   * are received, we look for elements with that guid and dispatch the keys to
   * them.
   */
  function KeyEventManager(opt_document) {
    this.document_ = opt_document || document;
    if (KeyEventManager.instance)
      throw new Error('KeyEventManager is a singleton.');
    this.onEvent_ = this.onEvent_.bind(this);
    this.document_.addEventListener('keydown', this.onEvent_);
    this.document_.addEventListener('keypress', this.onEvent_);
    this.document_.addEventListener('keyup', this.onEvent_);
    this.listeners_ = [];
  }
  KeyEventManager.instance = undefined;

  document.head.addEventListener('tr-unittest-will-run', function() {
    if (KeyEventManager.instance) {
      KeyEventManager.instance.destroy();
      KeyEventManager.instance = undefined;
    }
    KeyEventManager.instance = new KeyEventManager();
  });

  KeyEventManager.prototype = {
    addListener: function(type, handler, thisArg) {
      if (!thisArg.keyEventManagerGuid_) {
        thisArg.keyEventManagerGuid_ = tr.b.GUID.allocate();
        thisArg.keyEventManagerRefCount_ = 0;
      }
      thisArg.classList.add('key-event-manager-target');
      thisArg.keyEventManagerRefCount_++;

      var guid = thisArg.keyEventManagerGuid_;
      this.listeners_.push({
        guid: guid,
        type: type,
        handler: handler
      });
    },

    onEvent_: function(event) {
      // This does standard DOM event propagation of the given event, but using
      // guids to locate the thisArg for each listener. See event_target.js for
      // notes on how this works.
      var preventDefaultState = undefined;
      var stopPropagationCalled = false;

      var oldPreventDefault = event.preventDefault;
      event.preventDefault = function() {
        preventDefaultState = false;
        oldPreventDefault.call(this);
      };

      var oldStopPropagation = event.stopPropagation;
      event.stopPropagation = function() {
        stopPropagationCalled = true;
        oldStopPropagation.call(this);
      };

      event.stopImmediatePropagation = function() {
        throw new Error('Not implemented');
      };

      var possibleThisArgs = this.document_.querySelectorAll(
          '.key-event-manager-target');
      var possibleThisArgsByGUID = {};
      for (var i = 0; i < possibleThisArgs.length; i++) {
        possibleThisArgsByGUID[possibleThisArgs[i].keyEventManagerGuid_] =
            possibleThisArgs[i];
      }

      // We need to copy listeners_ and verify the thisArgs exists on each loop
      // iteration because the event callbacks can change the DOM and listener
      // list.
      var listeners = this.listeners_.concat();
      var type = event.type;
      var prevented = 0;
      for (var i = 0; i < listeners.length; i++) {
        var listener = listeners[i];
        if (listener.type !== type)
          continue;
        // thisArg went away.
        var thisArg = possibleThisArgsByGUID[listener.guid];
        if (!thisArg)
          continue;

        var handler = listener.handler;
        if (handler.handleEvent)
          prevented |= handler.handleEvent.call(handler, event) === false;
        else
          prevented |= handler.call(thisArg, event) === false;
        if (stopPropagationCalled)
          break;
      }

      // We want to return false if preventDefaulted, or one of the handlers
      // return false. But otherwise, we want to return undefiend.
      return !prevented && preventDefaultState;
    },

    removeListener: function(type, handler, thisArg) {
      if (thisArg.keyEventManagerGuid_ === undefined)
        throw new Error('Was not registered with KeyEventManager');
      if (thisArg.keyEventManagerRefCount_ === 0)
        throw new Error('No events were registered on the provided thisArg');
      for (var i = 0; i < this.listeners_.length; i++) {
        var listener = this.listeners_[i];
        if (listener.type == type &&
            listener.handler == handler &&
            listener.guid == thisArg.keyEventManagerGuid_) {
          thisArg.keyEventManagerRefCount_--;
          if (thisArg.keyEventManagerRefCount_ === 0)
            thisArg.classList.remove('key-event-manager-target');
          this.listeners_.splice(i, 1);
          return;
        }
      }
      throw new Error('Listener not found');
    },

    destroy: function() {
      this.listeners_.splice(0);
      this.document_.removeEventListener('keydown', this.onEvent_);
      this.document_.removeEventListener('keypress', this.onEvent_);
      this.document_.removeEventListener('keyup', this.onEvent_);
    },

    dispatchFakeEvent: function(type, args) {
      var e = new KeyboardEvent(type, args);
      return KeyEventManager.instance.onEvent_.call(undefined, e);
    }
  };

  KeyEventManager.instance = new KeyEventManager();

  return {
    KeyEventManager: KeyEventManager
  };
});
</script>
