/*
 * Taggy/History.js
 * TAGGY JavaScript Library
 *
 * 文字コード: UTF-8
 * 改行コード: LF
 *
 * ■使い方
 *
 */

if (typeof(Taggy) == 'undefined') var Taggy = function () {};

Taggy.History = function (name, attr) {

	var attribute = attr || {};

	this.media = name;
	this.medias = ['video', 'news', 'photo', 'blog', 'bookmark', 'podcast'];

	this.current = {
		media	: name,
		id		: attribute.id		|| null,
		tags	: attribute.tags	|| []
	};

	this.cookies = {};
	this.templates = {
		recommend : {},
		recommendSide : {},
		searchRecommend : {}
	};

	this.failed = {};

	//this.cookie = new HTTP.Cookies();
	this.id = attribute.id || 'taggy_history';
	this.name = (typeof name == 'undefined') ? 'taggy' : name;
	this.size = attribute.size || 2;
	this.expires = attribute.expires || '1M';
	//this.path = attribute.path || '/user/' + this.name;
	//this.path = attribute.path || '/' + this.name;
	this.path = attribute.path || '/';
	//this.domain = (location.hostname.match(/([^\.]+\.[^\.]+)$/)) ? RegExp.$1 : null;
	this.domain = null;

	this.config = {
		request : {
			limit : 256
		},
		cookie : {
			expires : 86400 * 28 * 1000 // ミリ秒
		},
		rating : {
			match : 10,
			point : 8,
			limit : 2,
			max : 16
		},
		search : {
			size : 8,
			limit : 4
		},
		article : {
			size : 16
		},
		recommend : {
			size : 32,
			limit : 64 
		},
		recommendSide : {
			size : 4
		},
		tag : {
			size : 3
		}
	};

	var copy = this;

	this.historyName = 'tah'; // Taggy Article History
	this.searchHistoryName = 'tsh'; // Taggy Search History
	this.ratingName  = 'ttr'; // Taggy Tag Rating

	this.list_name		= function () { return copy.name + '_history'; };
	this.tag_maps_name	= function () { return copy.name + '_history_tags'; };

};
Taggy.History.prototype.src = function (_tags, _attr) {

	var attribute = (typeof _attr == 'undefined') ? {} : _attr;

	// http://10.0.1.146:8080/user/media/new/jsonp.do?encoding=utf-8&callback=console.info&limit=4&media=video&query=cat
	var tags = (typeof _tags == 'undefined') ? '' : _tags.join(' ');

	//console.info('src tags: ', tags);

	return '' +
		'/user/media/new/jsonp.do' +
		'?encoding=utf-8' +
		'&callback=' + (attribute.callback || 'taggy_history.write') +
		'&limit=' + (attribute.limit || this.config.request.limit) +
		'&media=' + (attribute.media || this.media) +
		'&query=' + encodeURIComponent(tags);

};
Taggy.History.prototype.add = function (_id, _tags) {

	var id = (_id || this.current.id) + '';
	var tags = _tags || this.current.tags;

	var oldHistory = this.getHistory();
	var newHistory = [id];

	//if (id == oldHistory[0]) return;

	for (var i = 0; i < oldHistory.length; ++i) {
		if (id == oldHistory[i] || oldHistory[i] == 'undefined') continue;
		newHistory[newHistory.length] = oldHistory[i];
	}

	if (newHistory.length > this.config.article.size)
		newHistory.length = this.config.article.size;

	var oldRating = this.getRating();
	var newRating = {};
	var point = this.config.rating.point;
	var title = document.getElementsByTagName('h1')[0].innerHTML;

	for (var i = 0; i < tags.length; ++i) {
		var tag = tags[i];
		var TAG = tag.toUpperCase();
		var regex = new RegExp(TAG);
		newRating[TAG] = (title.toUpperCase().match(regex))
			? this.config.rating.match
			: (newRating[TAG])
				? newRating[TAG] + point
				: point;
		point = --point || 1;
	}

	var sorted = this.keys(newRating).sort(
		function (a, b) { return newRating[b] - newRating[a]; });

	var neoRating = {};

	for (var i = 0; i < sorted.length; ++i) {
		var tag = sorted[i];
		neoRating[tag] = newRating[tag];
	}

	var max = this.config.rating.max;

	for (var tag in oldRating) {
		var TAG = tag.toUpperCase();
		if (--oldRating[tag]) {
			neoRating[TAG] = (neoRating[TAG])
				? oldRating[tag] + neoRating[TAG]
				: oldRating[tag];

			if (neoRating[TAG] > max) neoRating[TAG] = max;
		}
	}

	var newHistoryString = Taggy.array2json(newHistory);
	var newRatingString = Taggy.hash2json(neoRating);

	//Taggy.Cookie.remove(this.historyName, this.path, location.hostname);
	//Taggy.Cookie.remove(this.ratingName, this.path, location.hostname);

	Taggy.Cookie.write(this.historyName, newHistoryString, this.expires, this.path, this.domain);
	Taggy.Cookie.write(this.ratingName,  newRatingString,  this.expires, this.path, this.domain);

	this.deleteCookie();

};
Taggy.History.prototype.addSearch = function (tags) {

	if (typeof tags == 'undefined' || tags.length == 0) return;

	var oldSearchHistory = this.getSearchHistory();
	var newSearchHistory = tags.concat();

	//if (newSearchHistory[0] == oldSearchHistory[0]) return;

	for (var i = 0; i < oldSearchHistory.length; ++i) {
		if (this.grep(newSearchHistory, oldSearchHistory[i]) ||
			oldSearchHistory[i] == 'undefined') continue;
		newSearchHistory[newSearchHistory.length] = oldSearchHistory[i];
	}

	if (newSearchHistory.length > this.config.search.size)
		newSearchHistory.length = this.config.search.size;

	var newSearchHistoryString = Taggy.array2json(newSearchHistory);

	//Taggy.Cookie.remove(this.searchHistoryName, this.path, location.hostname);
	Taggy.Cookie.write(this.searchHistoryName, newSearchHistoryString, this.expires, this.path, this.domain);

};
Taggy.History.prototype.deleteCookie = function () {
	//var old = new Date(2000, 1, 1);
	//var old_expires = old.toGMTString();

	//document.cookie = this.list_name() +'=0; expires='+ old_expires +'; path=/;';
	//document.cookie = this.list_name() +'=0; expires='+ old_expires +'; path=/'+ this.media +';';
	//document.cookie = this.list_name() +'=0; expires='+ old_expires +'; path=/user/'+ this.media +';';
	//document.cookie = this.tag_maps_name() +'=0; expires='+ old_expires +'; path=/;';
	//document.cookie = this.tag_maps_name() +'=0; expires='+ old_expires +'; path=/'+ this.media +';';
	//document.cookie = this.tag_maps_name() +'=0; expires='+ old_expires +'; path=/user/'+ this.media +';';

	Taggy.Cookie.remove(this.list_name(), '/');
	Taggy.Cookie.remove(this.list_name(), '/' + this.media);
	Taggy.Cookie.remove(this.list_name(), '/user/' + this.media);
	Taggy.Cookie.remove(this.tag_maps_name(), '/');
	Taggy.Cookie.remove(this.tag_maps_name(), '/' + this.media);
	Taggy.Cookie.remove(this.tag_maps_name(), '/user/' + this.media);
};
Taggy.History.prototype.array2json = function (_arr) {

	var arr = [];

	for (var i = 0; i < _arr.length; ++i) {
		var value = _arr[i] + '';
		arr[i] = value.replace(/'/g, "\\'");
	}

	return "['"+ arr.join("','") +"']";

};
Taggy.History.prototype.hash2json = function (_hash) {

	var hash = [];

	for (var key in _hash) {
		var value = _hash[key] + '';
		hash[hash.length] = "'"+ (key + '').replace(/'/g, "\\'") +"':'"+ value.replace(/'/g, "\\'") +"'";
	}

	return '{'+ hash.join(",") +'}';

};

Taggy.History.prototype.getHistory = function (_name) {

	var cookie_name = _name || this.historyName;
	//var value = decodeURIComponent(this.getCookies(cookie_name));
	var value = this.getCookies(cookie_name);
	var history_list = [];

	try {
		if (value == undefined || value == 'undefined' || value == '') {
			history_list = [];
		}
		else if (value.match(/^\[/) && value.match(/\]$/)) {
			history_list = eval(value);
		}
		else {
			history_list = eval('[' + value + ']');
		}
	}

	catch (e) {
		console.info(e);
	}

	return history_list;

};
Taggy.History.prototype.getSearchHistory = function (_name) {

	var cookie_name = _name || this.searchHistoryName;
	//var value = decodeURIComponent(this.getCookies(cookie_name));
	var value = this.getCookies(cookie_name);
	var history_list = [];

	try {
		if (value == undefined || value == 'undefined' || value == '') {
			history_list = [];
		}
		else if (value.match(/^\[/) && value.match(/\]$/)) {
			history_list = eval(value);
		}
		else {
			history_list = eval('[' + value + ']');
		}
	}

	catch (e) {
		console.info(e);
	}

	return history_list;

};
Taggy.History.prototype.getRating = function (_name) {

	var cookie_name = _name || this.ratingName;
	//var value = decodeURIComponent(this.getCookies(cookie_name));
	var value = this.getCookies(cookie_name);
	var tag_rating = {};

	try {
		if (value == undefined || value == 'undefined' || value == '') {
			tag_rating = {};
		}
		else if (value.match(/^\{/) && value.match(/\}$/)) {
			tag_rating = eval('(' + value + ')');
		}
		else {
			tag_rating = eval('({' + value + '})');
		}
	}

	catch (e) {
		console.info(e);
	}

	return tag_rating;

};
Taggy.History.prototype.getTagRanking = function () {

	var tagRating = this.getRating();
	var tags = this.keys(tagRating);
	tags.sort(function (a, b) { return tagRating[b] - tagRating[a]; });
	if (tags.length > this.config.rating.limit)
		tags.length = this.config.rating.limit;
	return tags;

};
//Taggy.History.prototype.getExpiresDate = function (time) {
//
//	var expires = new Date();
//	expires.setTime(expires.getTime() + (time || this.config.cookie.expires));
//	return expires;
//
//};
Taggy.History.prototype.getCookies = function (name) {

	if (this.cookies[name]) return this.cookies[name];

	var cookies = document.cookie.split(/;\s+/);

	for (var i = 0; i < cookies.length; ++i) {
		var hash = cookies[i].split('=');
		this.cookies[hash[0]] = decodeURIComponent(hash[1]);
	}

	return this.cookies[name];

};

Taggy.History.prototype.randomize = function (original) {

	var randomize = new Array();

	while(original.length)
		randomize[randomize.length] =
			original.splice(Math.floor(Math.random() * original.length), 1)[0];

	return randomize;

};
Taggy.History.prototype.keys = function (hash) {

	var keys = [];
	for (var key in hash) {
		keys[keys.length] = key;
	}
	return keys;

};
Taggy.History.prototype.grep = function (arr, key) {

	for (var i = 0; i < arr.length; ++i) {
		if (arr[i] == key) return true;
	}

	return false;

};
Taggy.History.prototype.list = function (_name) {

	var cookie_name = (typeof _name == 'undefined') ? this.list_name() : _name;
	var value = decodeURIComponent(Taggy.Cookie.read(cookie_name));
	var history_list = (value == 'undefined') ? {} : eval('[' + value + ']');

	//alert(
	//		this.list_name() + ': ' + value + "\n" +
	//		'document.cookie: ' + document.cookie.replace(/;\s+/g, ";\n"));

	return history_list;

};
Taggy.History.prototype.maps = function (_name) {

	var cookie_name = (typeof _name == 'undefined') ? this.tag_maps_name() : _name;
	var value = decodeURIComponent(Taggy.Cookie.read(cookie_name));
	var history_tag_maps = {};

	try {
		history_tag_maps = (value == 'undefined') ? {} : eval('({' + value + '})');
	}

	catch (e) {
		this.deleteCookie();
	}

	return history_tag_maps;

};
Taggy.History.prototype.tags = function (object_name) {

	var tagRating = this.getRating();
	var tags = this.keys(tagRating);
	var sorted = tags.sort(function (a, b) { return tagRating[b] - tagRating[a]; });
	return sorted;

};

/*
var recommendItems = [];
var recommendCount = 0;

Taggy.History.prototype.recommend = function (id, template) {

	if (id == undefined) return;
	if (template == undefined) return;

	this.boxId = id || this.boxId;
	this.templates.recommend[this.media] = template;

	//var tags = this.tags().concat();
	var tags = this.getTagRanking();
	//var tagRating = this.getRating();
	//var tags = this.keys(tagRating);
	var head = document.getElementsByTagName('head')[0];
	var script = document.createElement('script');

	if (tags.length == 0) return;

	//tags.sort(function (a, b) { return tagRating[b] - tagRating[a]; });

	//if (tags.length > this.config.rating.limit)
	//	tags.length = this.config.rating.limit;

	var shuffled = this.randomize(tags);

	//console.info('tags, ', tags);
	//alert('request tags: ' + tags.join(', '));

	script.type = 'text/javascript';
	script.charset = 'utf-8';
	script.src = this.src([shuffled[0]]);
	//script.src = this.src(tags);

	head.appendChild(script);

};
Taggy.History.prototype.write = function (response) {

	if (response.Entry.length == 0) return;

	var tagRating = this.getRating();
	var articleHistory = this.getHistory();
	var articleRating = {};
	var items = [];

	for (var i = 0; i < response.Entry.length; ++i) {
		var item = response.Entry[i];
		var identifier = item.identifier + '';

		if (this.grep(articleHistory, identifier)) continue;

		var title = item.title;
		var TITLE = title.toUpperCase();
		var tags = (item.subjects) ? item.subjects.concat() : [];
		var rate = 0;

		for (var n = 0; n < tags.length; ++n) {
			var tag = tags[n].subject;
			rate = rate + ((tagRating[tag]) ? tagRating[tag] - 0 : 0);
		}

		articleRating[identifier] = rate;
		items[items.length] = item;
	}

	if (items.length == 0) return;

	items.sort(
		function (a, b) {
			return articleRating[b.identifier] - articleRating[a.identifier]; });

	if (items.length > this.config.recommend.size)
		items.length = this.config.recommend.size;

	var ajp = new AjaxPages();
	var box = document.getElementById(this.boxId);
	var complete = function (req) {
		recommendItems = items;
		recommendCount = items.length;
		ajp.template = req.responseText;
		var processor = ajp.getProcessor();
		box.parentNode.style.display = 'block';
		box.innerHTML = processor();
	};
	var ajax = new Ajax.Request(
		this.templates.recommend[this.media],
		{
			method: 'get',
			asynchronous: true,
			onComplete: complete
		}
	);

};

Taggy.History.prototype.recommendSide = function (id, template, _media, onfailed) {

	if (_media == this.media) return;
	if (onfailed == undefined) onfailed = function(){};
	if (template == undefined) return onfailed();
	if (id == undefined) return onfailed();

	var media = _media || this.media;

	this.sideBoxId = id;
	this.templates.recommendSide[media] = template;
	this.failed[media] = onfailed;

	//var tags = this.tags().concat();
	//var tags = this.getTagRanking();
	var tagRating = this.getRating();
	var tags = this.keys(tagRating);
	var head = document.getElementsByTagName('head')[0];
	var script = document.createElement('script');
	var callback = 'taggy_history.write_side_' + media;

	if (tags.length == 0) return onfailed();

	tags.sort(function (a, b) { return tagRating[b] - tagRating[a]; });

	if (tags.length > this.config.rating.limit)
		tags.length = this.config.rating.limit;

	tags = this.randomize(tags);

	script.type = 'text/javascript';
	script.charset = 'utf-8';
	script.src = this.src(
		[tags[0]], { 'media' : media, 'callback' : callback });
	//script.src = this.src(
	//	tags, { 'media' : media, 'callback' : callback });

	head.appendChild(script);

};
Taggy.History.prototype.write_side_video = function (response) {

	this.writeSide(response, 'video');

};
Taggy.History.prototype.write_side_photo = function (response) {

	this.writeSide(response, 'photo');

};
Taggy.History.prototype.write_side_news = function (response) {

	this.writeSide(response, 'news');

};
Taggy.History.prototype.write_side_blog = function (response) {

	this.writeSide(response, 'blog');

};
Taggy.History.prototype.write_side_bookmark = function (response) {

	this.writeSide(response, 'bookmark');

};
Taggy.History.prototype.write_side_podcast = function (response) {

	this.writeSide(response, 'podcast');

};
Taggy.History.prototype.writeSide = function (response, media) {

	var onfailed = this.failed[media];

	if (response.Entry.length == 0) return onfailed();

	var tagRating = this.getRating();
	var articleHistory = this.getHistory();
	var articleRating = {};
	var items = [];

	for (var i = 0; i < response.Entry.length; ++i) {
		var item = response.Entry[i];
		var identifier = item.identifier + '';

		if (this.grep(articleHistory, identifier)) continue;

		var tags = (item.subjects) ? item.subjects.concat() : [];
		var rate = 0;

		for (var n = 0; n < tags.length; ++n) {
			var tag = tags[n].subject;
			rate = rate + (tagRating[tag] ? tagRating[tag] - 0 : 0);
		}

		articleRating[identifier] = rate;
		items[items.length] = item;
		//if (items.length == this.config.recommendSide.size) break;
	}

	if (items.length == 0) return;

	items.sort(
		function (a, b) {
			return articleRating[b.identifier] - articleRating[a.identifier]; });

	if (items.length > this.config.recommendSide.size)
		items.length = this.config.recommendSide.size;

	var ajp = new AjaxPages();
	var box = document.getElementById(this.sideBoxId);
	var complete = function (req) {
		recommendSideItems = items.concat();
		recommendSideCount = items.length;
		ajp.template = req.responseText;
		var processor = ajp.getProcessor();
		box.style.display = 'block';
		box.innerHTML += processor();
	};
	var ajax = new Ajax.Request(
		this.templates.recommendSide[media],
		{
			method: 'get',
			asynchronous: true,
			onComplete: complete
		}
	);

	//var template = ajp.load(this.templates.recommendSide[media]);
	//var processor = ajp.getProcessor();

	////eval('recommendSideItems' + media.toUpperCase() + '=items;');
	////eval('recommendSideCount' + media.toUpperCase() + '=items.length;');
	////recommendSideItems = items.concat();
	////recommendSideCount = items.length;
	//recommendSideItems = items.concat();
	//recommendSideCount = items.length;

	//box.style.display = 'block';
	//box.innerHTML += processor();

};

var searchRecommendItems = [];
var searchRecommendCount = 0;

Taggy.History.prototype.searchRecommend = function (boxId, template) {

	if (boxId == undefined) return;
	if (template == undefined) return;

	this.searchRecommendBoxId = boxId;
	this.templates.searchRecommend[this.media] = template;

	var head = document.getElementsByTagName('head')[0];
	var script = document.createElement('script');
	var callback = 'taggy_history.writeSearchRecommend';
	var searchHistory = this.getSearchHistory();

	if (searchHistory.length == 0) return;
	if (searchHistory.length > this.config.search.limit)
		searchHistory.length = this.config.search.limit;

	script.type = 'text/javascript';
	script.charset = 'utf-8';
	script.src = this.src(
		searchHistory, { 'media' : this.media, 'callback' : callback });

	head.appendChild(script);

};
Taggy.History.prototype.writeSearchRecommend = function (response) {

	if (response.Entry.length == 0) return;

	var tagRating = {};
	var tagPoint = this.config.rating.point;
	var searchHistory = this.getSearchHistory();

	for (var i = 0; i < searchHistory.length; ++i) {
		var tag = searchHistory[i];
		tagRating[tag.toUpperCase()] = tagPoint;
		tagPoint = --tagPoint || 1;
	}

	//console.info('tagRating: ', tagRating);

	var items = [];
	var articleRating = {};
	var articleHistory = this.getHistory();

	for (var i = 0; i < response.Entry.length; ++i) {
		var item = response.Entry[i];
		var identifier = item.identifier + '';

		if (this.grep(articleHistory, identifier)) continue;

		var tags = (item.subjects) ? item.subjects.concat() : [];
		var rate = 0;

		for (var n = 0; n < tags.length; ++n) {
			var tag = tags[n].subject;
			rate = rate + (tagRating[tag] || 0);
		}

		articleRating[identifier] = rate;

		items[items.length] = item;
	}

	if (items.length == 0) return;

	//console.info('articleRating: ', articleRating);

	items.sort(
		function (a, b) {
			return articleRating[b.identifier] - articleRating[a.identifier]; });

	if (items.length > this.config.recommend.size)
		items.length = this.config.recommend.size;

	var ajp = new AjaxPages();
	var box = document.getElementById(this.searchRecommendBoxId);
	var complete = function (req) {
		searchRecommendItems = items;
		searchRecommendCount = items.length;
		ajp.template = req.responseText;
		var processor = ajp.getProcessor();
		box.parentNode.style.display = 'block';
		box.innerHTML = processor();
	};
	var ajax = new Ajax.Request(
		this.templates.searchRecommend[this.media],
		{
			method: 'get',
			asynchronous: true,
			onComplete: complete
		}
	);

	//var template = ajp.load(this.templates.searchRecommend[this.media]);
	//var processor = ajp.getProcessor();

	//searchRecommendItems = items;
	//searchRecommendCount = items.length;
	//box.parentNode.style.display = 'block';
	//box.innerHTML = processor();

};
*/
