/**
 *
 * common.js
 *
 * @version 1.0
 * @author Tatsuhisa Ishikawa
 *
 */

if(!window.ex){ var ex = {}; }

(function(jQuery){

this.undefined = this.undefined;

//ex.version
ex.version = "1.0";

//ex.browser
ex.browser = (function(){
	var ua = navigator.userAgent;
	var _ua = ua.toLowerCase(),
		rwebkit = /(webkit)[ \/]([\w.]+)/,
		ropera = /(opera)(?:.*version)?[ \/]([\w.]+)/,
		rmsie = /(msie) ([\w.]+)/,
		rmozilla = /(mozilla)(?:.*? rv:([\w.]+))?/;
	var match = rwebkit.exec( _ua ) || ropera.exec( _ua ) || rmsie.exec( _ua ) || ua.indexOf("compatible") < 0 && rmozilla.exec( _ua ) || [];

	var version = parseFloat(match[2]);
	var isOpera = Object.prototype.toString.call(window.opera) == '[object Opera]';
	var isIE = !!window.attachEvent && !isOpera;
	return {
		version			:	version,
		isIE			:	isIE,
		isOpera			:	isOpera,
		isChrome		:	ua.indexOf('Chrome') > -1,
		isWebKit		:	ua.indexOf('AppleWebKit/') > -1,
		isGecko			:	ua.indexOf('Gecko') > -1 && ua.indexOf('KHTML') === -1,
		isMobileSafari	:   /Apple.*Mobile/.test(ua),
		isWin			:	/Win/.test(ua),
		isMac			:	/Mac/.test(ua),
		isQuirks		:	(ua.compatMode == "BackCompat" || isIE && version < 6)
	}
})();

// ex.environment
ex.environment = (function(){
	return {
		isLocal : !/^https?\:$/.test(location.protocol)
	}
})();

// Object Extend
(function(){
	var _toString = Object.prototype.toString,
		NULL_TYPE = 'Null',
		UNDEFINED_TYPE = 'Undefined',
		BOOLEAN_TYPE = 'Boolean',
		NUMBER_TYPE = 'Number',
		STRING_TYPE = 'String',
		OBJECT_TYPE = 'Object',
		FUNCTION_CLASS = '[object Function]',
		NUMBER_CLASS = '[object Number]',
		STRING_CLASS = '[object String]',
		ARRAY_CLASS = '[object Array]',
		DATE_CLASS = '[object Date]';
	
	function extend(destination, source) {
		for (var property in source)
			destination[property] = source[property];
		return destination;
	}
	
	function Type(o) {
		switch(o) {
		  case null: return NULL_TYPE;
		  case (void 0): return UNDEFINED_TYPE;
		}
		var type = typeof o;
		switch(type) {
		  case 'boolean': return BOOLEAN_TYPE;
		  case 'number':  return NUMBER_TYPE;
		  case 'string':  return STRING_TYPE;
		}
		return OBJECT_TYPE;
	}
	
	function keys(object) {
		if (Type(object) !== OBJECT_TYPE) { throw new TypeError(); }
		var results = [];
		for (var property in object) {
			if (object.hasOwnProperty(property)) {
				results.push(property);
			}
		}
		return results;
	}

	function values(object) {
		var results = [];
		for (var property in object)
			results.push(object[property]);
		return results;
	}
	
	extend(Object, {
		extend		: extend,
		keys		: keys,
		values		: values,
		clone		: function (a){ return extend({ }, a); },
		isFunction	: function (a){ return _toString.call(a) === FUNCTION_CLASS; },
		isArray		: function (a){ return _toString.call(a) === ARRAY_CLASS; },
		isNumber	: function (a){ return _toString.call(a) === NUMBER_CLASS; },
		isString	: function (a){ return _toString.call(a) === STRING_CLASS; },
		isDate		: function (a){ return _toString.call(a) === DATE_CLASS; },
		isUndefined	: function (a){ return typeof a === "undefined"; }
	});
})();


// Function Extend
Object.extend(Function.prototype, {
	delay : function (timeout) {
		var __method = this, args = slice.call(arguments, 1);
		timeout = timeout * 1000;
		return window.setTimeout(function() {
		  return __method.apply(__method, args);
		}, timeout);
	}
});


// Array Extend
(function(){
	var arrayProto = Array.prototype,
		slice = arrayProto.slice,
		_each = arrayProto.forEach;
		
	function each(iterator, context) {
		for (var i = 0, length = this.length >>> 0; i < length; i++) {
			if (i in this) iterator.call(context, this[i], i, this);
		}
	}
	if (!_each) _each = each;
	
	function clear() {
		this.length = 0;
		return this;
	}
	
	function first() { return this[0]; }
	function last() { return this[this.length - 1]; }
	function clone() { return slice.call(this, 0); }
	function inspect() { return '[' + this.map(Object.inspect).join(', ') + ']'; }
	function reverse(inline) { return (inline === false ? this.toArray() : this)._reverse(); }
	
	function uniq(sorted) {
		return this.inject([], function(array, value, index) {
			if (0 == index || (sorted ? array.last() != value : !array.include(value)))
				array.push(value);
			return array;
		});
	}
	
	function intersect(array) {
		return this.uniq().findAll(function(item) {
			return array.detect(function(value) { return item === value });
		});
	}
	
	function indexOf(item, i) {
		i || (i = 0);
		var length = this.length;
		if (i < 0) i = length + i;
		for (; i < length; i++)
			if (this[i] === item) return i;
		return -1;
	}
	
	function lastIndexOf(item, i) {
		i = isNaN(i) ? this.length : (i < 0 ? this.length + i : i) + 1;
		var n = this.slice(0, i).reverse().indexOf(item);
		return (n < 0) ? n : i - n - 1;
	}
	
	function concat() {
		var array = slice.call(this, 0), item;
		for (var i = 0, length = arguments.length; i < length; i++) {
			item = arguments[i];
			if (Object.isArray(item) && !('callee' in item)) {
				for (var j = 0, arrayLength = item.length; j < arrayLength; j++)
					array.push(item[j]);
			} else {
				array.push(item);
			}
		}
		return array;
	}
	
	function shuffle() {
	  var i = this.length;
	
	  while (--i) {
		var j = Math.floor(Math.random() * (i + 1));
		if (i == j) continue;
		var k = this[i];
		this[i] = this[j];
		this[j] = k;
	  }
	
	  return this;
	}
	
	if (!arrayProto._reverse) arrayProto._reverse = arrayProto.reverse;
	
	Object.extend(arrayProto, {
		_each:     _each,
		clear:     clear,
		first:     first,
		last:      last,
		reverse:   reverse,
		uniq:      uniq,
		intersect: intersect,
		clone:     clone,
		toArray:   clone,
		shuffle:	shuffle,
		inspect:   inspect
	});
	
	var CONCAT_ARGUMENTS_BUGGY = (function() {
		return [].concat(arguments)[0][0] !== 1;
	})(1,2)
	
	if (CONCAT_ARGUMENTS_BUGGY) arrayProto.concat = concat;
	if (!arrayProto.indexOf) arrayProto.indexOf = indexOf;
	if (!arrayProto.lastIndexOf) arrayProto.lastIndexOf = lastIndexOf;
})();


// ex.data
ex.data = {};
// ex.Abstract
ex.Abstract = {};
// ex.Class
ex.Class = (function(){
	var IS_DONTENUM_BUGGY = (function(){
		for(var p in {toString : 1 }){
			if(p === 'toString') return false;
		}
		return true;
	})();
	
	function subclass() {};
	function create() {
		var parent = null, properties = [];
		for (var i = 0, l = arguments.length; i < l; i++)
			properties.push(arguments[i]);
		
		if(Object.isFunction(properties[0]))
			parent = properties.shift();
		
		function klass() { this.initialize.apply(this, arguments); }
		
		Object.extend(klass, ex.Class.Methods);
		klass.superclass = parent;
		klass.subclasses = [];
		
		if (parent) {
			subclass.prototype = parent.prototype;
			klass.prototype = new subclass;
			parent.subclasses.push(klass);
		}
		for (var i = 0, length = properties.length; i < length; i++)
			klass.addMethods(properties[i]);
		
		if (!klass.prototype.initialize){
			klass.prototype.initialize = function(){};
			klass.prototype.bind = function( e, f ){ $(this).bind(e,f); return this; };
			klass.prototype.unbind = function( e, f ){ $(this).unbind(e,f); return this; };
			klass.prototype.trigger = function( e ){ $(this).trigger(e); return this; };
		}
		klass.prototype.constructor = klass;
		return klass;
	}
	
	function addMethods(source) {
		var ancestor = this.superclass && this.superclass.prototype,
		properties = Object.keys(source);
		if (IS_DONTENUM_BUGGY) {
			if (source.toString != Object.prototype.toString)
				properties.push("toString");
			if (source.valueOf != Object.prototype.valueOf)
				properties.push("valueOf");
		}
		for (var i = 0, length = properties.length; i < length; i++) {
			var property = properties[i], value = source[property];
			this.prototype[property] = value;
		}
		return this;
	}
	
	return {
		create : create,
		Methods: {
			addMethods: addMethods
		}
	};
})();

jQuery.extend({
	Abstract	:	ex.Abstract,
	Class		:	ex.Class
})



/* ex.Util
 ---------------------------------*/
ex.util = {};

ex.util.loadCSS = function (fn){
	var tag=document.createElement('link');
	tag.setAttribute("tyle","text/css");
	tag.setAttribute("rel","stylesheet");
	tag.setAttribute("href", fn);
	document.getElementsByTagName('head')[0].appendChild(tag);
}

ex.util.loadJavascript = function (fn){
	var tag=document.createElement('script');
	tag.setAttribute("tyle","text/javascript");
	tag.setAttribute("href", fn);
	document.getElementsByTagName('head')[0].appendChild(tag);
}

// js ファイルのパラメーターを取得できます
ex.util.getSrcParams = function (fn) {	
	var scripts = jQuery('script');
	var script;
	var src;
	var params = {};
	scripts.each(function(){
		src = $(this).attr('src');
		if(src && src.indexOf(fn) != -1) {
			script = this;
		}
	})
	if(script) {
		src = $(script).attr('src');
		var index = src.indexOf('?');
		if(index != -1){
			var query = src.substr(index + 1, src.length - (index + 1));
			var a = query.split('&');
			if(a){
				for(var k=0; k < a.length; k++ ){
					var p = a[k].split('=');
					if(p[0]){
						params[p[0]] = p[1];
					}
				}
				return params;
			}
		}
	}
	return false;
}


})(jQuery);
