function MorphAnalyzer(){
	this.query = "";
	this.block = 0;
	this.from_num = 0;
	this.to_num = 0;
	this.tfList = [];
	this.totalcount = 0;
	this.callback = null;
	this.initialize.apply(this,arguments);	
}

/**
 * 形態素解析を行いタグクラウドを生成
 */
MorphAnalyzer.prototype = {
	
	minLength : 2,
	maxLength: 7,
	maxTerms : 30,
	
	initialize : function(query,block,from_num,to_num){
		this.query = query;
		this.block = block;
		this.from_num = from_num;
		this.to_num = to_num;
	},
	
	/**
	 * TagCloudオブジェクトからよばれる
	 * @param {Object} interval
	 */
	callDoAnalyze : function(callback,interval){
		this.callback = callback;
		setTimeout(b(this,this.doAnalyze),interval);
	},
	
	include : function(tfList,target){
		var limit = Math.min(tfList.length,5);
		origin = target;
		for(var i = 0; i < limit; i++){
			var term = tfList[i][0];
			term = term.replace(" ","");
			target = target.replace(" ","");
			if(term != origin && term.search(target) >= 0){
				return true;
			}
		}
		return false;
	},

	
	removeStopWords : function(tfList){
		list = [];
		var query = this.query.replace(/[\s ]/g,"");
		var count = 0;
		var baseReg = new RegExp("[" + $R.escapeRegExp(query) + "]","g");
		var querylen = query.length;
		var queryRegList = $R.queryRegList;
		var reg_alpha_three = new RegExp();
		reg_alpha_three.compile(/^[a-zA-Z0-9]{1,2}$/);
		var added = {};
		for(var i = 0, n = tfList.length; i < n; i++){
			var item = tfList[i];
			var term = item[0];
			var tf = item[1];
			if (query.search(term) >= 0 || term.search(query) >= 0) {
				continue;
			}
			if(term.length > querylen && term.replace(baseReg,"").length <= 1){	//クエリに任意の1文字挿入しただけの単語を除去
				continue;	
			}
			if(added[term.toUpperCase()]){
				continue;
			}
			//数字,アルファベットは3文字以上
			if (term.match(reg_alpha_three)) {
				continue;
			}
			/*if(term.match(/^[^ぁ-ん]+[の][^ぁ-ん]+$/)){
				continue;
			}*/
			if($C.stopWords[term.toUpperCase()]){
				continue;
			}
			if(this.include(tfList,term)){
				continue;
			}
			var contain = false
			for(var j = 0, k = queryRegList.length; j < k; j++){
				if(term.match(queryRegList[j])){
					contain = true;
					break;
				}
			}
			
			if(contain){
				continue;
			}
			
			list.push(item);
			count++;
			added[term.toUpperCase()] = true;
			if(count >= this.maxTerms){
				break;
			}
		}
		return list;
	},
	
	doAnalyze : function(){
		var tf = {};
		for(var i = this.from_num; i <= this.to_num; i++){
			this.doAnalyzeItem(tf,$R.items[i]);
		}
		
		var tfList = [];
		$.each(tf,function(key,value){
			tfList.push([key,value]);
		});
		tfList.sort(function(a,b){
			return b[1] - a[1];
		});
		tfList = this.removeStopWords(tfList);
		var newTfList = [];
		var totalcount = 0;
		var maxCount = 0.0;
		var minCount = 100.0;
		var rank = 1;
		for(i = 0, n = Math.min(this.maxTerms,tfList.length) ; i < n; i++){
			maxCount = Math.max(maxCount,tfList[i][1]);
			minCount = Math.min(minCount,tfList[i][1]);
			tfList[i][2] = rank++;
			newTfList.push(tfList[i]);
			totalcount += tfList[i][1];
		}
		newTfList.sort(function(a,b){
			return b[0]  < a[0];
		});
		this.tfList = newTfList;
		this.totalcount = totalcount;
		this.maxCount = maxCount;
		this.minCount = minCount;
		this.callback(this.block,this.toHtml());
	},
	format_tag: '<nobr><span type="tag" class="morph tag #tagclass#" size="#size#" style="font-size:#size#%;" count="#count#" rank="#rank#">#term#</span></nobr>\r\n',
	//format_tag: '<nobr><span type="tag" class="morph ' + "#size#" + '" count="' + "#count#" +'">' + "#term#" + "</span></nobr>\r\n",
	//format_whitespace : '<span class="whitespace"> </span>\r\n',
	format_whitespace : ' ',
	reg_size : /#size#/g,
	s_count : "#count#",
	s_term : "#term#",
	format_header : "<span>#from#位　〜　#to#位</span>",
	
	toHtml : function(){
		var buf = [];
		buf.push(this.format_header.replace("#from#",this.from_num + 1).replace('#to#',this.to_num + 1));
		buf.push('<div class="cloud" id="cloud' + this.block + '" >\r\n');

		for(var i = 0, n = this.tfList.length; i<n; i++){
			var tf = this.tfList[i];
//			var size = this.getTagSize(tf[1],this.totalcount);
			var size = this.getTagSize2(tf[1],this.minCount,this.maxCount);
			var tagclass = this.getTagClass(size);
			buf.push(this.format_tag.replace(/#size#/g,size).replace(this.s_count,tf[1]).replace(this.s_term,tf[0]).replace('#tagclass#',tagclass).replace('#rank#',tf[2]));
			buf.push(this.format_whitespace);
		}
		buf.push('</div>\r\n');
		return buf.join('');
	},

	
	doAnalyzeItem : function(tfList,item){
		var query = $R.query;
		var s_undefined = "undefined";
		if ((typeof item.already == s_undefined)) {
			var already = {};
			var content = item.content;
			var tokens = content.match($C.morphReg);
			if (tokens && tokens.length >= 1) {
				for (var i = 0, n = tokens.length; i < n; i++) {
					var token = tokens[i];
					var english = false;
					if (already[token]) {
						continue;
					}
					//文字列長で制限
					if (token.length >= this.minLength && token.length <= this.maxLength) {
						if (typeof tfList[token] == s_undefined) {
							tfList[token] = 1;
						}
						else {
							tfList[token]++;
						}
						already[token] = true;
					}
				}
			}
			item.already = already;
		}
		else {
			var morphs = item.already;
			$.each(morphs,function(token,temp){
				if (typeof tfList[token] == s_undefined) {
						tfList[token] = 1;
					}
					else {
						tfList[token]++;
					}
			});
		}
	},
	
	getTagSize2 : function(count,min,max){
		var base = 80;
		var size = 80 + base * (count - min) / (max - min);
		return Math.floor(size);
	},

	getTagClass : function(size){
		if (size >= 160) {
			return "tag1";
		}
		else {
			return "";
		}
	}
	/*
	getTagSize : function(count,total){
		var ratio = count / total;
		if(ratio > this.tagsize['biggest'][0]){
			return this.tagsize['biggest'][1];
		}
		else if(ratio > this.tagsize['bigger'][0]){
			return this.tagsize['bigger'][1];
		}
		else if(ratio > this.tagsize['normal'][0]){
			return this.tagsize['normal'][1];
		}
		else{
			return this.tagsize['small'][1];
		}
	}*/
};

var TagCloud  = {
	
	completeFlags : [],
	interval : 200,
	
	initialize : function(){
		$('#tagcloud').get(0).innerHTML = "";
	},
	
	//RerankJpオブジェクトから呼びだされる
	createTagCloud : function(){
		
		var resultNum = $R.items.length;
		var unit = Math.ceil($R.items.length / 2);
		//var unit = $R.items.length;
//		var unit = $R.requestUnit;
		var loop = Math.floor((resultNum-1) / unit) + 1;
		var query = $R.query;
		this.loop = loop;
		this.completeFlags = new Array(loop);
		$.map(this.completeFlags, function(){
			return false
		});
		this.startTagIndicator();
		for(var i = 0; i < loop; i++){
			var analyzer = new MorphAnalyzer(query,i,i * unit, Math.min(resultNum -1,(i + 1) * unit - 1));
			$("#tagcloud").append('<div id="wrap' + i + '"></div');
			analyzer.callDoAnalyze(b(this,this.recieveResult),this.interval * i);
		}
		/*
		//一つだけ生成
		this.completeFlags = [false];
		this.startTagIndicator();	
		var analyzer = new MorphAnalyzer(query,0,0, resultNum -1);
		$("#tagcloud").append('<div id="wrap0"></div');
		analyzer.callDoAnalyze(b(this,this.recieveResult),100);	
		*/
	},
	
	
	recieveResult : function(block,cloud){
		$("#wrap" + block).get(0).innerHTML = cloud;
		this.completeFlags[block] = true;
		if(this.checkComplete()){
			this.stopTagIndicator();
		}
		else{
			
		}
	},
	
	//TagCloudが全て生成し終わったかを確認する
	checkComplete: function(){
		for(var i = 0, n = this.completeFlags.length; i < n ; i++){
			if(!this.completeFlags[i]){
				return false;
			}
		}
		return true;
	},
	

	
	startTagIndicator : function(){
		$("#tagloading").get(0).innerHTML = '<div id="indicator"><img src="' + $C.indicator + '" /></div>';
	},
	
	stopTagIndicator : function(){
		$("#tagloading").get(0).innerHTML = "";
	}
	
};

var $T = TagCloud;



