/**************************************************************************/
/************************** Function.prototype ****************************/
/**************************************************************************/
(function(/*Function.prototype*/self){

	self.inherit = function(superClass){
		/* See http://www.skipup.com/~peace/javascript/ */
		function Temp(){}
		this.__super__ = superClass;
		Temp.prototype = superClass.prototype;
		this.prototype = new Temp;
		this.prototype.__super__ = function(){
			arguments[arguments.length-1].callee.__super__.apply(
				this, arguments); };
		this.prototype.constructor = this; };
	
	/* Never use __temp__ as the ECMAScript production "Identifier"
	   except as a temporary property which is not used in other scope. */
	if (!self.call) {
		self.call = function(){
			var _this = arguments[0], a = [];
			_this.__temp__ = arguments.callee;
			for (var i=1,len=arguments.length; i<len; i++)
				a.push(arguments[i]);
			eval('_this.__temp__(' +
				(a.length == 0)? '' : a.join(',') + ')');
			delete _this.__temp__; }; }

	if (!self.apply) {
		self.apply = function(){
			var _this = arguments[0], args = arguments[1], a = [];
			_this.__temp__ = arguments.callee;
			if (args)
				for (var i=0,len=args.length; i<len; i++)
					a.push(args[i]);
			eval('_this.__temp__(' +
				(a.length == 0)? '' : a.join(',') + ')');
			delete _this.__temp__; }; }

})(Function.prototype);


/**************************************************************************/
/**************************** Array.prototype *****************************/
/**************************************************************************/
(function(/*Array.prototype*/self){
	/* Array.prototype以下のメソッドを呼ぶときIEが独自の見えねえ方法で
	型判定を行うもんだから（not instanceof）、継承ができねえんです。
	継承してえんです（グリーンマイル風）。 */
	if (!self.push) {
		self.push = function(item) {
			return this[this.length] = item; }; }

	if (!self.pop) {
		self.pop = function(){
			var last = this[this.length-1];
			delete this[this.length-1];
			return last; }; }

	try { undefined; } catch(e) { undefined = void 0; }
	// try catchの方がよっぽど怪しいという罠
	if (!self.slice) {
		/* See Standard Ecma-262 ECMAScript Language Specification */
		self.slice = function(start, end) {
			var A = new Array, max = Math.max, min = Math.min, len = this.length;
			var k = (start < 0)?
				max(len + start, 0) : min(start, len);
			if (end === undefined)
				end = len;
			var h = (end < 0)?
				max(len + end, 0) : min(end, len);
			var n = 0;
			while(k < h) {
				if (this[k] !== undefined)
					A[n] = this[k];
				k++;
				n++; }
			return A; }; }

	self.insert = function(/*[]*/ary, /*int*/point) {
		var front = this.slice(0, point);
		var last = this.slice(point);
		return front.concat(ary, last); };

	self.indexOf = function(key){
		for (var i=0,len=this.length; i<len; i++)
			if (key == this[i])
				return i;
		return -1; };

})(Array.prototype);


/**************************************************************************/
/************************* Class Identifier *******************************/
/**************************************************************************/
function Identifier(baseURI, id){
	/* Handle URI, URL and OS-paths as identifier.

	Copy left. Comment? w650s@mcn.ne.jp */
	this.__base = baseURI;
	this.__id = (id !== undefined)? id : '';
	this.__cache = null;
}

(function(/*Identifier.prototype*/self){

	self.changeID = function(id){
		this.__cache = null;
		this.__id = id; };

	self.changeBase = function(URI){
		this.__base = this.resolve(URI); };

	self.getscheme = function(){
		return this.getcomponents()[0]; };

	self.getauthority = function(){
		return this.getcomponents()[1]; };

	self.getpath = function(){
		return this.getcomponents()[2]; };

	self.getquery = function(){
		return this.getcomponents()[3]; };

	self.getfragment = function(){
		return this.getcomponents()[4]; };

	self.getfilename = function(){
		return this.getpath().split('/').pop(); };

	self.__import__ = function(){
		for (var i=0,len=arguments.length; i<len; i++) {
			var html = '<script type="text/javascript" src="'+
				this.resolve(arguments[i]+'.js')+'"><\/script>';
			document.write(html); } };
	
	self.getcomponents = function(){
		/* => [scheme, authority, path, query, fragment] */
		var cache;
		if (cache = this.__cache)
			return cache[1];
		cache = [];
		var uri = this.resolve();
		REG_URI.test(uri);
		var scheme = RegExp.$1, authority = RegExp.$2, path = RegExp.$3,
			query = '', fragment = '', i;
		if ((i = path.indexOf('#')) != -1) {
			fragment = path.slice(i+1, path.length);
			path = path.slice(0, i); }
		if ((i = path.indexOf('?')) != -1) {
			query = path.slice(i+1, path.length);
			path = path.slice(0, i); }
		var components = [scheme, authority, path, query, fragment];
		cache[0] = this.__id, cache[1] = components;
		this.__cache = cache;
		return components; };

	self.resolve = function(/*optional*/relativeURI){
		var ruri = (relativeURI === undefined)? this.__id : relativeURI;
		if (/^[\#\?]/.test(ruri) || ruri == '')
			return this.__base + ruri;
		if (ruri.match(REG_PATH))
			return pathToUri();
		if (REG_URI.test(ruri))
			return ruri;
		var buri = this.__base;
		if (buri.match(REG_PATH))
			buri = pathToUri();
		REG_URI.test(buri);
		var scheme = RegExp.$1, authority = RegExp.$2, path = RegExp.$3;
		if (ruri.slice(0,2) == '//')
			return scheme + ':' + ruri;
		if (ruri.charAt(0) == '/')
			return scheme + '://' + authority + ruri;
		var i = path.lastIndexOf('/');
		path = (i != -1)? path.slice(0, i) : '';
		if (ruri.indexOf('./') == 0)
			ruri = ruri.slice(2, ruri.length);
		var components = [scheme+':/', authority];
		while (ruri.indexOf('../') == 0 && path.length) {
			ruri = ruri.slice(3, ruri.length);
			path = ((i = path.lastIndexOf('/', path.length-2)) != -1)?
				path.slice(0, i) : ''; }
		if (path)
			components.push(path);
		components.push(ruri);
		return components.join('/');
		function pathToUri(){
			return [
				'file://', RegExp.$1, RegExp.$2.replace(/\\/g, '/')
			].join('/');
		}
	};

	// private, final variables and its getters
	var REG_PATH = /^([a-zA-Z]:)\\([^\s]+)/;
	self.getRePath = function(){ return REG_PATH; };

	var REG_URI = /^([a-zA-Z0-9]+):\/\/(\/?[^\s\/]+)\/(.*)/;
	self.getReURI = function(){ return REG_URI; };

})(Identifier.prototype);


/**************************************************************************/
/******************************* Globals **********************************/
/**************************************************************************/

URI = new Identifier(location.href);

__path__ = {"Class":"../js/class", "Main":"../js"};

function __from__(path) {
	var p = path.split('.');
	var root = __path__[p[0]];
	if (!root)
		throw new Error('Path '+ p[0] +' not defined.');
	var a = [root];
	for (var i=1,len=p.length; i<len; i++)
		a.push(p[i]);
	return new Identifier(URI.resolve(a.join('/')+'/'));
}

function __require__(/* *args */) {
	var i=0, a=[];
	for (var len=arguments.length; i<len-1; i++) {
		try {
			eval(arguments[i]); }
		catch(e) {
			a.push(arguments[i]); } }
	if (a.length > 0)
		throw new Error(a.join(', ') + 'are required.' +
			arguments[i+1]);
}
