var Subject = Class.create();
Subject.prototype = {
    _getEventCBs: function(event) {
        if (!this.subjects) {
            this.subjects = new Object();
        }
        
        if (!this.subjects[event]) {
            this.subjects[event]= new Array();
        }
        
        return this.subjects[event];
    },
    
    observe: function(event, callback) {
        this._getEventCBs(event).push(callback);
    },
    
    unobserve: function(event, callback) {
        this._getEventCBs(event).splice(this._getEventCBs(event).indexOf(callback), 1);
    },
    
    raiseEvent: function(event) {
        var args = $A(arguments);
        this._getEventCBs(event).each(function(callback) {
            var urgs = args.slice(1);
            callback.apply(callback, urgs);
        });
    }    
}

function _body_defineSheet(cssStr, id) {
	var style = $(id);
	
	if (style != null)
	   style.parentNode.removeChild(style)
	   
	style = document.createElement("style");
	style.setAttribute("type", "text/css");
	style.setAttribute("id", id);
	if(style.styleSheet){// IE
		style.styleSheet.cssText = cssStr;
	} else {
		var cssText = document.createTextNode(cssStr);
		style.appendChild(cssText);
	}
	document.getElementsByTagName("head")[0].appendChild(style);
}

var PeriodicalExecuterNamed = Class.create();

PeriodicalExecuterNamed.ids = new Array();

PeriodicalExecuterNamed.finish = function(key) {
	if (PeriodicalExecuterNamed.ids[key] != undefined && PeriodicalExecuterNamed.ids[key] != null) {
	    clearInterval(PeriodicalExecuterNamed.ids[key]);
		PeriodicalExecuterNamed.ids[key] = null;
	}
}

PeriodicalExecuterNamed.prototype = {
  initialize: function(callback, frequency, key) {
    this.callback = callback;
    this.frequency = frequency;
	this.key = key;
    this.currentlyExecuting = false;
	
    this.registerCallback();
  },

  registerCallback: function() {
	this.finish();
	if (this.frequency > 0) {
    	PeriodicalExecuterNamed.ids[this.key] = setInterval(this.onTimerEvent.bind(this), this.frequency * 1000);
	}
	this.onTimerEvent();
  },

  finish: function() {
	  PeriodicalExecuterNamed.finish(this.key);
  },
  
  onTimerEvent: function() {
    if (!this.currentlyExecuting) {
      try {
        this.currentlyExecuting = true;
        this.callback();
      } finally {
        this.currentlyExecuting = false;
      }
    }
  }
}

Effect.iPhoneMove = Class.create();
Object.extend(Object.extend(Effect.iPhoneMove.prototype, Effect.Base.prototype), {
  initialize: function() {
    var options = Object.extend({
      x:    0,
      y:    0
    }, arguments[0] || {});
    this.start(options);
  },
  setup: function() {
    this.originalLeft = this.options.x < 0 ? -this.options.x : 0;
    this.originalTop = this.options.y < 0 ? -this.options.y : 0;
  },
  update: function(position) {
    window.scrollTo(this.options.x * position + this.originalLeft, this.options.y  * position + this.originalTop);
  }
});


