var Beholder = Class.create({
  initialize: function(element){
    this.element = element;
    $H(this.events).each(function(pair){
      var handler = pair.value;
      if(!this.bubbling){
        var orghandler = handler;
        handler = function(ev){
          orghandler.call(this, ev);
          ev.stop();
        };
      }
      Event.observe(this.element, pair.key, handler.bindAsEventListener(this));
    }.bind(this));
  },
  events: {},
  bubbling: true
});
Object.extend(Beholder, {
  create: function(){
    var args = $A(arguments);

    if(!args.size() || (args[0].prototype && !(args[0].prototype instanceof Beholder)))
      return Class.create(this, {});

    var superinit = function($super){
      var siargs = $A(arguments);
      siargs.shift();
      $super(siargs.shift());
      init.apply(this, siargs);
    };

    var methods = null;
    var base = this;
    if(args[0].prototype){
      methods = args[1] || {};
      base = args[0];
    } else{
      methods = args[0]; 
    }

    if(methods.initialize){
      var init = methods.initialize;
      methods.initialize = superinit;
    }

    return Class.create(base, methods);
  },
  arise: function(){
    this.beholders.each(function(behavior){
      $H(behavior).each(function(pair){
        var selector = pair.key;
        if(typeof pair.value == 'function'){
          if(pair.value.prototype instanceof Beholder){
            var BeholderClass = pair.value;
            $$(selector).each(function(e){
              behavior = new BeholderClass(e);
            });
          } else{
            var matches = pair.key.match(/(.+):(.+)$/);
            if(matches[1] && matches[2]){
              $$(matches[1]).each(function(e){
                Event.observe(e, matches[2], pair.value.bindAsEventListener(e));
              });
            }
          }
        } else if(typeof pair.value == 'object'){
          $H(pair.value).each(function(bpair){
            $$(selector).each(function(e){
              Event.observe(e,bpair.key,bpair.value.bindAsEventListener(e));
            });
          });
        }
      });
    });
  },
  beholders: []
});

Event.behold = function(rule){
  Beholder.beholders.push(rule);
};
Event.observe(document, 'dom:loaded', Beholder.arise.bind(Beholder));
