/**
* @class Ext.EventManager
*/
Ext.apply(Ext.EventManager, function(){
   var resizeEvent,
       resizeTask,
       textEvent,
       textSize,
       D = Ext.lib.Dom,
       propRe = /^(?:scope|delay|buffer|single|stopEvent|preventDefault|stopPropagation|normalized|args|delegate)$/,
       unload = Ext.EventManager._unload,
       curWidth = 0,
       curHeight = 0,
       // note 1: IE fires ONLY the keydown event on specialkey autorepeat
       // note 2: Safari < 3.1, Gecko (Mac/Linux) & Opera fire only the keypress event on specialkey autorepeat
       // (research done by @Jan Wolter at http://unixpapa.com/js/key.html)
       useKeydown = Ext.isWebKit ?
                   Ext.num(navigator.userAgent.match(/AppleWebKit\/(\d+)/)[1]) >= 525 :
                   !((Ext.isGecko && !Ext.isWindows) || Ext.isOpera);

   return {
       _unload: function(){
           Ext.EventManager.un(window, "resize", this.fireWindowResize, this);
           unload.call(Ext.EventManager);    
       },
       
       // private
       doResizeEvent: function(){
           var h = D.getViewHeight(),
               w = D.getViewWidth();

            //whacky problem in IE where the resize event will fire even though the w/h are the same.
            if(curHeight != h || curWidth != w){
               resizeEvent.fire(curWidth = w, curHeight = h);
            }
       },

       /**
        * Adds a listener to be notified when the browser window is resized and provides resize event buffering (100 milliseconds),
        * passes new viewport width and height to handlers.
        * @param {Function} fn      The handler function the window resize event invokes.
        * @param {Object}   scope   The scope (<code>this</code> reference) in which the handler function executes. Defaults to the browser window.
        * @param {boolean}  options Options object as passed to {@link Ext.Element#addListener}
        */
       onWindowResize : function(fn, scope, options){
           if(!resizeEvent){
               resizeEvent = new Ext.util.Event();
               resizeTask = new Ext.util.DelayedTask(this.doResizeEvent);
               Ext.EventManager.on(window, "resize", this.fireWindowResize, this);
           }
           resizeEvent.addListener(fn, scope, options);
       },

       // exposed only to allow manual firing
       fireWindowResize : function(){
           if(resizeEvent){
               resizeTask.delay(100);
           }
       },

       /**
        * Adds a listener to be notified when the user changes the active text size. Handler gets called with 2 params, the old size and the new size.
        * @param {Function} fn      The function the event invokes.
        * @param {Object}   scope   The scope (<code>this</code> reference) in which the handler function executes. Defaults to the browser window.
        * @param {boolean}  options Options object as passed to {@link Ext.Element#addListener}
        */
       onTextResize : function(fn, scope, options){
           if(!textEvent){
               textEvent = new Ext.util.Event();
               var textEl = new Ext.Element(document.createElement('div'));
               textEl.dom.className = 'x-text-resize';
               textEl.dom.innerHTML = 'X';
               textEl.appendTo(document.body);
               textSize = textEl.dom.offsetHeight;
               setInterval(function(){
                   if(textEl.dom.offsetHeight != textSize){
                       textEvent.fire(textSize, textSize = textEl.dom.offsetHeight);
                   }
               }, this.textResizeInterval);
           }
           textEvent.addListener(fn, scope, options);
       },

       /**
        * Removes the passed window resize listener.
        * @param {Function} fn        The method the event invokes
        * @param {Object}   scope    The scope of handler
        */
       removeResizeListener : function(fn, scope){
           if(resizeEvent){
               resizeEvent.removeListener(fn, scope);
           }
       },

       // private
       fireResize : function(){
           if(resizeEvent){
               resizeEvent.fire(D.getViewWidth(), D.getViewHeight());
           }
       },

        /**
        * The frequency, in milliseconds, to check for text resize events (defaults to 50)
        */
       textResizeInterval : 50,

       /**
        * Url used for onDocumentReady with using SSL (defaults to Ext.SSL_SECURE_URL)
        */
       ieDeferSrc : false,
       
       // protected, short accessor for useKeydown
       getKeyEvent : function(){
           return useKeydown ? 'keydown' : 'keypress';
       },

       // protected for use inside the framework
       // detects whether we should use keydown or keypress based on the browser.
       useKeydown: useKeydown
   };
}());

Ext.EventManager.on = Ext.EventManager.addListener;


Ext.apply(Ext.EventObjectImpl.prototype, {
   /** Key constant @type Number */
   BACKSPACE: 8,
   /** Key constant @type Number */
   TAB: 9,
   /** Key constant @type Number */
   NUM_CENTER: 12,
   /** Key constant @type Number */
   ENTER: 13,
   /** Key constant @type Number */
   RETURN: 13,
   /** Key constant @type Number */
   SHIFT: 16,
   /** Key constant @type Number */
   CTRL: 17,
   CONTROL : 17, // legacy
   /** Key constant @type Number */
   ALT: 18,
   /** Key constant @type Number */
   PAUSE: 19,
   /** Key constant @type Number */
   CAPS_LOCK: 20,
   /** Key constant @type Number */
   ESC: 27,
   /** Key constant @type Number */
   SPACE: 32,
   /** Key constant @type Number */
   PAGE_UP: 33,
   PAGEUP : 33, // legacy
   /** Key constant @type Number */
   PAGE_DOWN: 34,
   PAGEDOWN : 34, // legacy
   /** Key constant @type Number */
   END: 35,
   /** Key constant @type Number */
   HOME: 36,
   /** Key constant @type Number */
   LEFT: 37,
   /** Key constant @type Number */
   UP: 38,
   /** Key constant @type Number */
   RIGHT: 39,
   /** Key constant @type Number */
   DOWN: 40,
   /** Key constant @type Number */
   PRINT_SCREEN: 44,
   /** Key constant @type Number */
   INSERT: 45,
   /** Key constant @type Number */
   DELETE: 46,
   /** Key constant @type Number */
   ZERO: 48,
   /** Key constant @type Number */
   ONE: 49,
   /** Key constant @type Number */
   TWO: 50,
   /** Key constant @type Number */
   THREE: 51,
   /** Key constant @type Number */
   FOUR: 52,
   /** Key constant @type Number */
   FIVE: 53,
   /** Key constant @type Number */
   SIX: 54,
   /** Key constant @type Number */
   SEVEN: 55,
   /** Key constant @type Number */
   EIGHT: 56,
   /** Key constant @type Number */
   NINE: 57,
   /** Key constant @type Number */
   A: 65,
   /** Key constant @type Number */
   B: 66,
   /** Key constant @type Number */
   C: 67,
   /** Key constant @type Number */
   D: 68,
   /** Key constant @type Number */
   E: 69,
   /** Key constant @type Number */
   F: 70,
   /** Key constant @type Number */
   G: 71,
   /** Key constant @type Number */
   H: 72,
   /** Key constant @type Number */
   I: 73,
   /** Key constant @type Number */
   J: 74,
   /** Key constant @type Number */
   K: 75,
   /** Key constant @type Number */
   L: 76,
   /** Key constant @type Number */
   M: 77,
   /** Key constant @type Number */
   N: 78,
   /** Key constant @type Number */
   O: 79,
   /** Key constant @type Number */
   P: 80,
   /** Key constant @type Number */
   Q: 81,
   /** Key constant @type Number */
   R: 82,
   /** Key constant @type Number */
   S: 83,
   /** Key constant @type Number */
   T: 84,
   /** Key constant @type Number */
   U: 85,
   /** Key constant @type Number */
   V: 86,
   /** Key constant @type Number */
   W: 87,
   /** Key constant @type Number */
   X: 88,
   /** Key constant @type Number */
   Y: 89,
   /** Key constant @type Number */
   Z: 90,
   /** Key constant @type Number */
   CONTEXT_MENU: 93,
   /** Key constant @type Number */
   NUM_ZERO: 96,
   /** Key constant @type Number */
   NUM_ONE: 97,
   /** Key constant @type Number */
   NUM_TWO: 98,
   /** Key constant @type Number */
   NUM_THREE: 99,
   /** Key constant @type Number */
   NUM_FOUR: 100,
   /** Key constant @type Number */
   NUM_FIVE: 101,
   /** Key constant @type Number */
   NUM_SIX: 102,
   /** Key constant @type Number */
   NUM_SEVEN: 103,
   /** Key constant @type Number */
   NUM_EIGHT: 104,
   /** Key constant @type Number */
   NUM_NINE: 105,
   /** Key constant @type Number */
   NUM_MULTIPLY: 106,
   /** Key constant @type Number */
   NUM_PLUS: 107,
   /** Key constant @type Number */
   NUM_MINUS: 109,
   /** Key constant @type Number */
   NUM_PERIOD: 110,
   /** Key constant @type Number */
   NUM_DIVISION: 111,
   /** Key constant @type Number */
   F1: 112,
   /** Key constant @type Number */
   F2: 113,
   /** Key constant @type Number */
   F3: 114,
   /** Key constant @type Number */
   F4: 115,
   /** Key constant @type Number */
   F5: 116,
   /** Key constant @type Number */
   F6: 117,
   /** Key constant @type Number */
   F7: 118,
   /** Key constant @type Number */
   F8: 119,
   /** Key constant @type Number */
   F9: 120,
   /** Key constant @type Number */
   F10: 121,
   /** Key constant @type Number */
   F11: 122,
   /** Key constant @type Number */
   F12: 123,

   /** @private */
   isNavKeyPress : function(){
       var me = this,
           k = this.normalizeKey(me.keyCode);
       return (k >= 33 && k <= 40) ||  // Page Up/Down, End, Home, Left, Up, Right, Down
       k == me.RETURN ||
       k == me.TAB ||
       k == me.ESC;
   },

   isSpecialKey : function(){
       var k = this.normalizeKey(this.keyCode);
       return (this.type == 'keypress' && this.ctrlKey) ||
       this.isNavKeyPress() ||
       (k == this.BACKSPACE) || // Backspace
       (k >= 16 && k <= 20) || // Shift, Ctrl, Alt, Pause, Caps Lock
       (k >= 44 && k <= 46);   // Print Screen, Insert, Delete
   },

   getPoint : function(){
       return new Ext.lib.Point(this.xy[0], this.xy[1]);
   },

   /**
    * Returns true if the control, meta, shift or alt key was pressed during this event.
    * @return {Boolean}
    */
   hasModifier : function(){
       return ((this.ctrlKey || this.altKey) || this.shiftKey);
   }
});