
/*
	Observer
*/
var Observer = Class.extend({}, {

	initialize: function() {},

	update: function(event) {}
});


/*
	View
*/

var View = Class.extend(Observer, {

	initialize: function(model) {
		$C(Observer).initialize.call(this);

		this.model = model;
		this.controller = new Controller(this);

		this.model.attach(this);
	}
});


/*
	Controller
*/
var Controller = Class.extend(Observer, {

	initialize: function(view) {
		$C(Observer).initialize.call(this);

		this.view = view;
		this.model = view.model;	
		this.model.attach(this);
	}
});


/*
	Model
*/
var Model = Class.extend({}, {

	initialize: function(options) {
		this.registry = [];
		
		Object.extend(this,options);
	},

	//	Observer interface
	attach: function(observer) {
		if (!this.registry.include(observer)) 
			this.registry.push(observer);
	},	

	detach: function(observer) {
		this.registry = this.registry.without(observer);
	},

	notify: function(event) {
		this.registry.each(function(observer) {
			observer.update(event);
		});
	}
});


var CollectionModel = Class.extend(Model, {

	initialize: function(options) {
		$C(Model).initialize.call(this,options);
		this.objects = {};
	},

	// Data interface	
	add: function(object) {
		if (this.objects[object.id]) return false;

		this.update(object);
		return true;
	},
	
	update: function(object) {
		this.objects[object.id] = object;
		object.collection = this;		
	},
	
	append: function(newobjects) {
		var newobjs = [];
		for (var i = 0; i < newobjects.length; i++) {
			if (this.add(newobjects[i])) newobjs.push(newobjects[i]);
		}
		return newobjs;
	},

	remove: function(object) {
		object.collection = null;
		delete this.objects[object.id];
	},

	clear: function() {
		$H(this.objects).values().each(function(node) {
			node.collection = null;
		});
		this.objects = {};
	},
	
	list: function() {
		return ($H(this.objects).values());
	}
});

/*
	MVCEvent
*/
var MVCEvent = Class.extend({}, {

	initialize: function(type,data) {
		this.type = type;
		this.data = data;
	}
});
