/*-------------------------------------------------------
suggest.js
depends on prototype.js(http://prototype.conio.net/)
@version  V1.0(Modified 2007/04/20)
--------------------------------------------------------*/
/*
--------------------------------------------------------
suggest.js - Input Suggest
Version 1.4.0 (Update 2006/05/11)

- onozaty (http://www.enjoyxstudy.com)

Released under the Creative Commons License(Attribution 2.1 Japan):
 http://creativecommons.org/licenses/by/2.1/jp/

depends on prototype.js(http://prototype.conio.net/)

For details, see the web site:
 http://www.enjoyxstudy.com/javascript/suggest/

--------------------------------------------------------
*/
Util.createSuggest = function  ( id ,input, syncId, recommendArea, maskingArea, candidateList) {
	   if(this.instances == null) this.instances = new Array(); 	   
	   var instance = null;
  	   for (var i = 0; i < this.instances.length ; i++) {
  		    if( this.instances[i].id == id ){
  			return this.instances[i];
  			}
  		}
  		instance = new Util.Suggest(id ,input, syncId, recommendArea, maskingArea, candidateList);
  		this.instances.push(instance);	 
    },

Util.Suggest.prototype = {
  // options
  interval  : 500,
  dispMax   : 10,
  minLength : 2,
  ignoreCase: true,
  ignoreDup : false,
  highlight : true,
  color		: 'red',

  initialize: function ( id, input, syncId, recommendArea, maskingArea, candidateList) {
 
    this.id            = id;
    this.syncId	       = syncId; 
    this.syncObj	   = null; 
    
    //
    this.input         = $(input);
    this.maskingArea   = $(maskingArea);
    this.recommendArea = $(recommendArea);
    this.candidateList = candidateList;

    // recommendation list
    this.recommendList      = null;
    this.recommendIndexList = null;
    this.cursorPosition     = null;

    // Event Timer
    this.timer              = null;

    // variable for backup! 
    this.inputValueBackup   = null;
    this.oldText            = null; 
    //this.getInputText();
	this.selectedText       = null;
	// item Tagname 
    this.itemTag		    = 'div';
    
    // regist event
	this.bindEvent();

	// refresh area
    this.clearRecommendArea();
  },
  
  nan:function(){
   	this.recommendList = null;
   	this.recommendIndexList = null;
  },
  
  bindEvent: function(){
    Event.observe(this.input, 'focus',    this.checker.bindAsEventListener(this),   false);
    Event.observe(this.input, 'blur',     this.blur.bindAsEventListener(this),      false);
   	if(window.opera){
   	    //Failed!! Why?
   		//Event.observe(this.input, 'keydown', this.keyevent.bindAsEventListener(this),  false);
   		Event._observeAndCache(this.input, 'keypress', this.keyevent.bindAsEventListener(this), false);
   	}else{
   		Event.observe(this.input, 'keypress', this.keyevent.bindAsEventListener(this),  false);
   	}
    
  },

  isModified: function(){
     return !(this.getInputText() == this.oldText);
  },
  
  setTimer:function (){
   	this.timer = setTimeout(this.checker.bind(this), this.interval);
  },
  
  checker: function() {
    if (this.isModified()) {
      this.backupInputValue();
      this.search();
    }
    if (this.timer) clearTimeout( this.timer );
    this.setTimer();
  },

  stopEvent: function(event){
    Event.stop(event);
  },
  	
  rewindInputValue:function(){
    this.input.value = this.inputValueBackup;
    this.backupInputValue();
    //alert("rewind");
  },	
  	
  backupInputValue:function(){
    this.oldText = this.getInputText();
  },
  	
  keyevent: function(event) {
    if (!this.timer) {
      this.setTimer();
    }
    if ( event.keyCode == Event.KEY_UP || event.keyCode == Event.KEY_DOWN) {
      this.stopEvent(event);
      this.moveActiveList(event.keyCode);
      return false;
    } 
    if (this.recommendList) {
    	if (event.keyCode == Event.KEY_RETURN) {
    		this.stopEvent(event);
        	this.clearRecommendArea();
            this.syncInputText();
    	} else if (event.keyCode == Event.KEY_ESC) {
    		this.stopEvent(event);
        	this.clearRecommendArea();
        	this.rewindInputValue();
     	}
    }
  },

  search: function() {
    // clear 
    this.clearRecommendArea();

    var text = Util.convertToKana(this.getInputText());
    if ( this.isEmpty(text) ) return;
    
    var resultList 	= new Array();
    var temp 		= null;

    this.recommendIndexList = new Array();

    for (var i = 0; i < this.candidateList.length; i++) {

      if ((temp = this.isMatch(this.candidateList[i], text)) != null) {
      	if( this.ignoreDup || !this.isDuplicated(this.candidateList[i],resultList)){
        	resultList.push(temp);
        	this.recommendIndexList.push(i);      	
      	}
        if ( resultList.length >= this.dispMax) break;
      }
    }

    if (resultList != 0){
      this.createRecommendArea(resultList);
      this.revealMask();
    }
  },
  
  retreiveAirport:function(fqn){
  	var re = /\([A-Z]{3}\)/;
  	var airportCode = fqn.match(re);
  	if(!airportCode){
  		return '';
  	}
  	//alert(airportCode[0]);
  	return airportCode[0].substring(0,5);  
  },
  
  isDuplicated: function (code, backupList){
      for (var i = 0; i < backupList.length; i++) {
      	if ( backupList[i].indexOf(this.retreiveAirport(code)) > 0){
      	//debug
      	//alert(this.retreiveAirport(code)+" "+ backupList[i]);
      		return true;
      	}
      }
      return false;
  },
  
  isEmpty: function(element){
     if( element && element.length >= this.minLength) {
     	 return false;
   	 }
     return true;
  },
  
  resizeMask: function(){
    this.maskingArea.style.height = this.recommendArea.scrollHeight;
    this.maskingArea.style.width = this.recommendArea.scrollWidth;
  },
  	  
  hideMask: function(){
  	this.maskingArea.style.display='none';
  	this.resizeMask();
  },
  
  revealMask: function(){
  	this.maskingArea.style.display='';
  	this.resizeMask(); 
  },
  
  clearRecommendArea: function() {
    this.recommendArea.innerHTML = '';
    this.recommendArea.style.display = 'none';
   	this.hideMask();
    this.cursorPosition = null;
  },

  isMatch: function( value, pattern) {

    var pos;

    if (this.ignoreCase) {
      pos = value.toLowerCase().indexOf(pattern.toLowerCase());
    } else {
      pos = value.indexOf(pattern);
    }

    if (pos == -1) return null;

    if (this.highlight) {
      return (Util.escapeHTML(value.substr(0, pos)) + 
             '<strong><font color="'+
             Util.escapeHTML(this.color)+
             '">'      + 
             Util.escapeHTML(value.substr(pos, pattern.length)) +
             '</font></strong>' + 
             Util.escapeHTML(value.substr(pos + pattern.length)));
    } else {
      return value;
    }
  },

  createRecommendArea: function(resultList) {

    this.recommendList = new Array();
    this.inputValueBackup = this.input.value;

    for (var i = 0; i < resultList.length; i++) {
      var element = document.createElement(this.itemTag);
      element.innerHTML = resultList[i];
      this.recommendArea.appendChild(element);
   	  Event.observe(element, 'mousedown', new Function('event', 'this.itemClick(event, ' + i + ');').bindAsEventListener(this), false);
      Event.observe(element, 'mouseover', new Function('event', 'this.itemOver(event, ' + i + ');').bindAsEventListener(this), false);
      Event.observe(element, 'mouseout' , new Function('event', 'this.itemOut(event, ' + i + ');').bindAsEventListener(this), false);

      this.recommendList.push(element);
    }
    this.recommendArea.style.display = 'block';
  },

  moveActiveList: function(keyCode) {

    if (!this.recommendList || this.recommendList.length == 0){
      return;
    }

    this.unactive();
    if (keyCode == Event.KEY_UP) {
      if (this.cursorPosition == null) {
        this.cursorPosition = this.recommendList.length -1;
      }else{
        this.cursorPosition--;
        if (this.cursorPosition < 0) {
          this.cursorPosition = null;
          this.rewindInputValue();
          return;
        }
      }
    }else{
      if (this.cursorPosition == null) {
        this.cursorPosition = 0;
      }else{
        this.cursorPosition++;
      }
      if (this.cursorPosition >= this.recommendList.length) {
        this.cursorPosition = null;
        this.rewindInputValue();
        return;
      }
    }
    this.active(this.cursorPosition);
  },

  active: function(index) {
    this.activeItem(this.recommendList[index]);
    this.setInputText(this.candidateList[this.recommendIndexList[index]]);
    this.oldText = this.getInputText();
    this.input.focus();
  },

  unactive: function() {
    if (this.recommendList != null 
        && this.recommendList.length > 0
        && this.cursorPosition != null) {
      this.unactiveItem(this.recommendList[this.cursorPosition]);
    }
  },

  blur: function(event) {
    this.unactive();
    this.backupInputValue();
    if (this.timer) clearTimeout(this.timer);
    setTimeout(this.clearRecommendArea.bind(this),500);
  },

  itemClick: function(event, index) {
   	this.unactive();
   	this.cursorPosition = index;
   	this.selectedText  = this.candidateList[this.recommendIndexList[index]];
   	this.active(index);
   	setTimeout(this.syncInputTextForClick.bind(this),100);
  },

  itemOver: function(event, index) {
    var element = Event.element(event);
    this.overItem(element);
  },

  itemOut: function(event, index) {

    var element = Event.element(event);

    if (!this.recommendList) return;

    if (index == this.cursorPosition) {
      this.activeItem(element);
    }else{
      this.unactiveItem(element);
    }
  },

  activeItem: function(elmement) {
    elmement.className = 'active_suggest';
  },

  unactiveItem: function(elmement) {
    elmement.className = '';
  },

  overItem: function(elmement) {
    elmement.className = 'over';
  },

  getInputText: function() {
    return this.input.value;
  },

  setInputText: function(text) {
    this.input.value = text;
  },
  
  syncInputText: function() {
    this.oldText = this.input.value;
	if(this.getSyncObj()){
    	this.syncObj.setInputText(this.getInputText()) ; 
   	 	this.syncObj.backupInputValue() ;
	}
  },
  
  syncInputTextForClick: function() {
	if(this.getSyncObj()){
    	this.syncObj.setInputText(this.selectedText) ; 
   	 	this.syncObj.backupInputValue() ;
   	 	this.setInputText(this.selectedText) ;
   	 	this.backupInputValue() ;    
	}
  },
  
  getSyncObj:function(){
  	if(!this.syncObj || this.syncObj.id!=this.syncId){
		this.syncObj = Util.getInstance(this.syncId);
	} 
	return this.syncObj;
  },
  
  resetText:function(){
    this.input.value = "";
    this.oldText = "";
  }
}
