if (typeof(Ficia) == 'undefined') Ficia = {};

Ficia.Permalink = function(args){
	// parse to uri hash
	this.uri_base = args.uri_base;
	if (args.apply_to_canonical) this.apply_to_canonical = true;
};

Ficia.Permalink.prototype = {
	listeners: [],
	triggers: {},
	permalink_callback: [],
	mode: null,
	path: '',
	uri_base: '',
	mode_lock: false,
	lock_listener: false,
	apply_to_canonical: false,

	changeMode: function(new_mode,args){
		if (this.mode_lock) return;
		this.mode = new_mode,
		this.broadcast(args);
	},

	addListener: function(listener){
		this.listeners.push(listener);
	},

	// listeners に対して mode='detection' で送って、現在の hash の中身に対応する描画を行う
	// このモードで呼ばれた listener は { mode: 'mode', args: {} } な形で return する
	modeDetection: function(){
		var self = this;
		var hash = location.hash;
		if (!hash) return;

		var listeners = self.listeners;
		var detected = false;
		var path_query = location.hash.split('?', 2);
		var path = path_query.shift().replace(/\/+/g, '/').replace(/^#+/, '');
		var params = {};
		var query = path_query.shift();
		if (query) {
			var queries = query.split('&');
			if (queries.length > 0) {
				$.each(queries, function(i){
					var keyval = queries[i].split('=');
					if (keyval.length != 2) return;
					params[decodeURIComponent(keyval[0])] = decodeURIComponent(keyval[1]);
				});
			}
		}

		if (self.lock_listener) return;
		$.each(listeners, function(i){
			if (detected) return;
			var ret = listeners[i](self, 'detection', { hash: hash, path: path, path_list: path.split('/'), params: params });
			if (!ret) return;
			self.mode = ret.mode;
			detected = true;
		});
		if (!detected) self.changeMode('top');
	},

	// mode の変更が有ったら、各リスナーに通知して path を作成してもらう
	// 各リスナーは mode を元に処理するかどうか決め、 args の内容を元に path を作る
	broadcast: function(args){
		var self = this;
		if (self.lock_listener) return;
		self.path = '';
		if (!args) args = {};

		if (self.mode == 'top') {
		} else {
			var listeners = self.listeners;
			$.each(listeners, function(i){
				listeners[i](self, self.mode, args);
			});
		}


		// change hash
		if (!(location.hash == '' && self.path == '')) { // for Fx 3.0.x hack javascript:location.hash='' するとリロードしやがる
			location.hash = self.path;
		}

		var permalink;
		if (self.path) {
			permalink = self.uri_base + 'pl/' + self.path;
		} else {
			permalink = self.uri_base;
		}

		// change canonical
		if (self.apply_to_canonical) {
			var tmp = permalink.split('?', 1);
			$('link[rel=canonical]').attr('href', tmp[0]);
		}

		$.each(self.permalink_callback, function(i){
			self.permalink_callback[i](permalink);
		});
	},

	// permalink 開いた時に処理すべき内容を trigger として登録して、必要な部分だけ必要な時に呼び出す
	addTrigger: function(type, callback){
		var self = this;
		if (! self.triggers[type]) self.triggers[type] = [];
		self.triggers[type].push(callback);
	},

	callTrigger: function(type, args){
		var self = this;
		var triggers = self.triggers[type];
		if (!triggers) return;
		var trigger;
		while (trigger = triggers.shift()) {
			trigger(self, args);
		}
	},

	_: ''
};
// javascript:alert($('link[rel=canonical]').attr('href'))
