
var ivEvent = new Object({
  __list: {},
  __isReady: false,
  __message: [],

  Init: function() {
    this._ivEventOnLoadInit();
  },
  
  Attach: function(name, callback) {
    var obj = window.document;
    if (window.addEventListener) {
      obj.addEventListener(name, callback, false);
    } else if (window.attachEvent) {
      obj.attachEvent("on"+name, callback);
    } else {
      var fn = obj["on"+name];
      obj["on"+name] = function() {
        callback.apply(this, arguments);
        if (fn) fn.apply(this, arguments);
      }
    }
  },

  Stop: function(e) {
    var event = e || self.event;
    event.cancelBubble = true;
    if (event.stopPropagation) event.stopPropagation();
  },

  _ivEventOnLoad: function(e) {
    var event = e || self.event;
//alert(iv(event.type, ivEvent.__result, event));
//alert(ivEvent);
    if (ivEvent.__isReady) return;
    // if (event) ivEvent.__message.push(event.type);
    ivEvent.__isReady = true;
    ivEvent.Go('domready');
  },

  _ivEventOnLoadInit: function() {

    if (window.addEventListener) {
      document.addEventListener("DOMContentLoaded", function() {
        document.removeEventListener("DOMContentLoaded", arguments.callee, false);
        ivEvent.__message.push('DOMContentLoaded');
        ivEvent._ivEventOnLoad.apply(this, arguments);
      }, false);
      window.addEventListener("load", function() {
        document.removeEventListener("load", arguments.callee, false);
        ivEvent.__message.push('load');
        ivEvent._ivEventOnLoad.apply(this, arguments);
      }, false);

    } else if (window.attachEvent) {
      document.attachEvent("onreadystatechange", function() {
        if (document.readyState == "complete") {
          // check: interactive
          // document.detachEvent( "onreadystatechange", arguments.callee );
          ivEvent.__message.push('onreadystatechange');
          ivEvent._ivEventOnLoad.apply(this, arguments);
        }
      });
      window.attachEvent("onload", function() {
        ivEvent.__message.push('onload');
        ivEvent._ivEventOnLoad.apply(this, arguments);
      });
      
      // magic IE
      if (document.documentElement.doScroll) {
        ivEvent.__IeHack = setInterval(function() {
          var temp = document.createElement('div');
          try {
            // temp.doScroll(); // Technique by Diego Perini
            // ivEvent.__message += '.';
            document.body.appendChild(temp);
            document.body.removeChild(temp);
            temp = null;
          } catch (e) {
            temp = null;
            return;
          }
          if (ivEvent.__IeHack) clearInterval(ivEvent.__IeHack);
          //ivEvent.__message += document.readyState;
          ivEvent.__message.push('magic IE');
          ivEvent._ivEventOnLoad({'type':'TIMEOUT'});
        }, 10);
      }
      
    } else {
      var fn = window.onload;
      window.onload = function() {
        ivEvent.__message.push('window.onload');
        ivEvent._ivEventOnLoad.apply(this, arguments);
        if (fn) fn.apply(this, arguments);
      }
    }

// if(document.readyState) {
//  ivEvent.__hReady = setInterval(function() {
//         var state = document.readyState;
//         if (state == 'loaded' || state == 'complete') {
//           if (ivEvent.__hReady) clearInterval(ivEvent.__hReady);
//           ivEvent.__result = 1;
//           ivEvent._ivEventOnLoad();
//         }
//       }, 50);
// }


  },

  __Push: function(sender, action, callback) {
    if (!this.__list[action]) this.__list[action] = [];
    this.__list[action].push( {'sender':sender, 'action':action, 'callback':callback} );
  },

  __Add: function(sender, action, callback) {
    // TODO: AttachEvent
    switch (action) {
      case 'domready':
        if (this.__isReady) {
          callback.call(this);
        } else {
          this.__Push(sender, action, callback);
        }
        break;
      case 'escape':
        this.__Push(sender, action, callback);
        // onkeydown ?
        window.document['onkeypress'] = function() {ivEvent.__OnKeyPress.apply(this, arguments)};
        // ivEvent.Attach( 'keypress', function() {ivEvent.OnKeyPress.apply(this, arguments)} );
        break;
      case 'mousedown':
        this.__Push(sender, action, callback);
        window.document['onmousedown'] = function() {
          ivEvent.__OnMouseDown.apply(this, arguments);
        };
        break;
      case 'mousedownoutside':
        this.__Push(sender, action, callback);
        window.document['onmousedown'] = function() {
          ivEvent.__OnMouseDown.apply(this, arguments);
        };
        sender['onmousedown'] = function(e) {
          ivEvent.Stop(e);
        };
        break;
//       case 'blur':
//         this.__Push(sender, action, callback);
//         window.document['onblur'] = function() { ivEvent.__OnBlur.apply(this, arguments)};
      default:
        this.__Push(sender, action, callback);
        break;
    }
  },

//   Add: function(action, callback) {
//     this.__Add(null, action, callback);
//   },
  Register: function(sender, action, callback) {
    this.__Add(sender, action, callback);
  },

  Unregister: function(sender, action) {
    if (!this.__list[action]) return;
    var list = this.__list[action];
    for (var i=0; i<list.length; i++) {
      if (list[i].sender === sender) {
        list.splice(i, 1);
      }
    }
    switch (action) {
      case 'domready':
        break;
      case 'escape':
        if (list.length==0) window.document['onkeypress'] = null;
        break;
      case 'mousedown':
      case 'mousedownoutside':
        if (list.length==0) window.document['onmousedown'] = null;
        break;
//       case 'blur':
//         if (list.length==0) window.document['onblur'] = null;
//         break;
      default:
        break;
    }
  },


  __OnKeyPress: function(e) {
    var event = e || self.event;
    if (ivEvent.HasAction('escape') && event.keyCode==27) {
      ivEvent.Go('escape');
    }
  },
  __OnMouseDown: function(e) {
    var event = e || self.event;
    if (ivEvent.HasAction('mousedown')) {
      ivEvent.Go('mousedown');
    }
    if (ivEvent.HasAction('mousedownoutside')) {
      ivEvent.Go('mousedownoutside');
    }
  },
//   __OnBlur: function(e) {
//     var event = e || self.event;
//     if (ivEvent.HasAction('blur')) {
//       ivEvent.Go('blur');
//     }
//   },

  
  HasAction: function(action) {
    return !!(this.__list[action]);
  },
  
  Go: function(action) {
    if (!this.__list[action] || !this.__list[action].length) return;
    var list = this.__list[action];
//    if (['escape','mousedownoutside'].indexOf(action)>-1) {
    if (action==='escape' || action==='mousedownoutside') {
      var obj = list.pop();
//      alert(iv(obj));
      obj.callback.call(ivEvent, obj.sender);
    } else {
      // ie! for (var i in list) {
      for (var i=0; i<list.length; i++) {
        list[i].callback.call(ivEvent, list[i].sender);
      }
    }
  }


});

ivEvent.Init();
