/**
 * apply経由でスコープを保持して関数を呼び出す
 */

function AutoComplete(){
	this.id = "";
	this.textbox = null;
	this.initialzie.apply(this,arguments);
}

AutoComplete.prototype = {
	id : "",
	prevtext : "",
	prevquery : "",
	timeout : null,
	$textbox : null,
	delay : 200,
	$suggests : null,
	hasFocus : false,
	active : -1,
	cache : Array(),
	
	initialzie : function(id){
		this.id = id;
		var $textbox = $("#" + id);
		this.$textbox = $textbox;
		this.cache = new Array();
		this.prevtext = $textbox.val();
		$textbox.bind("keypress",b(this,this.onKeyDown));
		$textbox.bind("blur",b(this,this.onBlur));
		$textbox.bind("focus",b(this,this.onFocus));
		var div = document.createElement("div");
		div.setAttribute("class","ac_results");
		div.id = "suggests";
		$suggests = $(div);
		$suggests.hide();
		$suggests.css("position","absolute");
		$("body").append($suggests);
		this.$suggests = $suggests;
		this.checkValue();
	},
	
	onFocus : function(){
		this.hasFocus = true;
	},

	onBlur : function(){
		this.hasFocus = false;
		this.hideResults();
	},
	
	//一定期間ごとにテキストボックスの入力に変更が無いかチェックを行う
	checkValue : function(){
		if (this.hasFocus) {
			if(this.forceTextChange){
				this.prevtext = this.$textbox.val();
				this.forceTextChange = false;
			}
			var val = this.$textbox.val();
			if (this.prevtext != val) {
				this.prevtext = val;
				this.onTextChange();
			}
		}
		setTimeout(b(this,this.checkValue),200);
	},
	
	//矢印を押した際に候補をハイライトする
	onKeyDown : function(event){
		switch(event.keyCode){
			case 38: //up
				this.moveSelect(-1);
				break;
			case 40:	//down
				this.moveSelect(1);			
				break;
		}
	},
		
	//テキストボックスの入力値をサーバに投げる
	onTextChange: function(){
		var v = this.$textbox.val();
		v = v.replace(/^[ 　]+/, "").replace(/[ 　]+$/, "");
		v = v.replace("　"," ");
		//ａＺＡｚ
		v = v.replace(/[ａ-ｚＡ-Ｚ]+/,"");
		if (v.length >= 1) {
			if (this.prevquery == v) {
			}
			else {
				log("getresult::" + v + "::");
				this.prevquery = v;
				this.getResult(v);
			}
		}
		else{
			this.hideResultsNow();
		}
	},


	
	hideResults: function(){
		if (this.timeout) {
			clearTimeout(this.timeout);
			this.timeout = null;
		}
		t = setTimeout(b(this, this.hideResultsNow), 200);
		this.timeout = t;
	},

	hideResultsNow: function(){
		this.$suggests.html("")
		this.$suggests.hide();
	},
  

	showResults: function(){
		var textbox = this.$textbox.get(0);
		var pos = this.findPos(textbox);
		var width = this.$textbox.width();
		log("width=" + width);
		$suggests.css({
			width: parseInt(width) + "px",
			top: (pos.y + textbox.offsetHeight) + "px",
			left: pos.x + "px"
		});
		$suggests.show();
	},
		
	//テキストボックスのデータを基に補完クエリを取得する
	getResult : function(text){
		if (this.cache && this.cache[text]) {
			this.receiveResult(this.cache[text],text);
		}
		else {
			req = new Request();
			req.get(text, b(this, this.receiveResult));
		}
	},
	
	receiveResult : function(results){
		log("Receive");
		this.renderResult(results);
	},
	
	format : '<ul>#s</ul>',
	
	renderResult: function(results){$
		if (!results || results.length == 1) {
			this.hideResultsNow();
		}
		var query = results.pop();
		this.cache[query] = results;
		if(results.length == 1
			&& this.$textbox.val() == results[0]){
				this.hideResultsNow();
		}
		this.hideResultsNow();
		$suggest = this.$suggest;
		var ul = document.createElement("ul");
		var index = 0;
		for (var i = 0, n = results.length; i < n; i++) {
			var li = document.createElement("li");
			li.innerHTML = results[i];
			li.setAttribute("_index",index++);
			ul.appendChild(li);
			$(li).hover(function(){ //mouseenter
				$("li", ul).removeClass("ac_over");
				$(this).addClass("ac_over");
			}, function(){ //mouseout
				$(this).removeClass("ac_over");
			});
			$(li).click(function(e){
				e.preventDefault();
				e.stopPropagation();
				$("#textQuery").val($(this).text());
			});
		}
		log("Render");
		this.$suggests.append(ul);
		this.showResults();
	},
	
	moveSelect : function(step){
		
		var lis = $("#suggests li");
		if(!lis) return;
		var active = this.active;
		active += step;
		
		if(active < 0){
			active = lis.length - 1;
		}
		else if(active >= lis.size()){
			active = 0
		}
		lis.removeClass("ac_over");
		$(lis[active]).addClass("ac_over");
		this.$textbox.val($(lis[active]).get(0).textContent);
		this.forceTextChange = true;
		this.active = active;
	},
		
	clickTerm : function(event){
		var element = event.target;
		term = element.textContent;
		var li = element.parentNode;
		var text = li.textContent;
		var phrase = text.replace(term,'"' + term + '"');
		this.$textbox.val(phrase);
	},
	
	findPos : function(obj) {
		var curleft = obj.offsetLeft || 0;
		var curtop = obj.offsetTop || 0;
		while (obj = obj.offsetParent) {
			curleft += obj.offsetLeft
			curtop += obj.offsetTop
		}
		return {x:curleft,y:curtop};
	},
	
	
}


Request = function(){
	p : null,
	callback = null;
	query = null;
}

count = 1;
totalCount = 0;

Request.prototype = {
	
	base : "./php/auto_complete.php",
	
	get : function(query,callback){
		log("start get "　+ query)
		this.query = query;
		
		this.callback = callback;
		var url = this.base + "?c=" + encodeURIComponent(query) + "&count=" + count;
		log(url);
		count++;
		$.get(url,b(this,this.receive));	
	},
	
	receive : function(data){
		items = data.split(/,/g);
		c = Number(items[0]);
		log(items.length)
		var results = [];
		log(c);
		
		for(var i = 1, n = items.length; i < n; i++){
			results.push(items[i]);
		}
		log("finish" + " " + c + "::" + totalCount);
		results.push(this.query);
		if (c > totalCount){	//最新のリクエスト結果
			totalCount = c;
			this.callback(results);
		}
		else{	
			//古いりくえすとけっかは表示しない
//			this.callback([this.query]);
		}
	},
}

/*
$(document).ready(function(){
	comp = new AutoComplete("textQuery");
})
*/

