var suggest_types = {
  'suggest' : '',
  'recommend' : '関連単語',
  'related' : '関連単語',
  'narrow' : ''
};
var suggests = [
  {'input':'search', 'format':'xml','client':'goo'}
];
var services = {
'search':{
'cond0':'normal',
'cond1':'normal',
'cond2':'normal',
'cond3':'normal'
	}
};

var Suggest = Class.create();
Suggest.prototype = {
  initialize: function()
  {
    this.suggest  = null;           // 'ul' element to show suggests
    this.extend   = null;           // 'div' element to show extension of suggests
    this.cursor   = -1;             // cursor to point one of suggests
    this.cand_ary = new Array();    // array of suggests
    this.timerID  = null;           // timer ID
    this.MT       = '';             // copied value of MT input element
    this.input    = null;           // MT input element
    this.checked  = 'cond0';        // selected checkbox
    this.form     = $('search_form'); // searchbod form element
    this.sugchk   = $('sugchk');
    if (this.sugchk) Event.observe(this.sugchk, 'click', this.enable.bindAsEventListener(this));
    this.ajax_url = '/Api/suggest';
    this.service  = null;
    this.format   = null;
    this.client   = null;
    this.qgr_flag = 1; 
    for (var i = 0; i < suggests.length; i++) {
      var inputs = this.form.getElementsByTagName('input');
      for (var j = 0; j < inputs.length; j++) {
        // set events for inputs
        if (inputs[j].name == suggests[i].input) {
          if (navigator.appName=='Microsoft Internet Explorer')
            Event.observe(inputs[j],  'keyup',    this.keyDown.bindAsEventListener(this));
          else
            Event.observe(inputs[j],  'keydown',  this.keyDown.bindAsEventListener(this));
          Event.observe(inputs[j],    'focus',    this.focus.bindAsEventListener(this));
          Event.observe(inputs[j],    'click',    this.clear.bindAsEventListener(this));
          if (i == 0) inputs[j].focus();
        }

        // set events for radio buttons
        if (i == 0) {
          for (var key in services[suggests[0].input]) {
            if (key == inputs[j].id) {
              Event.observe(inputs[j], 'click',  function(event) {
                this.checked = Event.element(event).id;
                this.switchModule();
              }.bindAsEventListener(this));
            }
          }
          if (inputs[j].checked) this.checked = inputs[j].id;
        }
      }
    }

    this.switchModule();
    Event.observe(document.body, 'click',    this.clear.bindAsEventListener(this));
    Event.observe(this.form,     'submit',   this.submit.bindAsEventListener(this));
    Event.observe(window,        'resize',   this.resize.bindAsEventListener(this));
    this.enable();
    return;
  },

  focus: function(event)
  {
    var input = Event.element(event);
    for (var i = 0; i < suggests.length; i++) {
      if (input.name == suggests[i].input) break;
    }
    if (i < suggests.length) {
      this.MT      = input.value;
      this.input   = input;
      this.switchModule();
      this.format  = 'xml';
      this.client  = 'bitem';//suggests[i].client;
    }
    Event.stop(event);
    return false;
  },
  
  switchModule: function()
  {
    if (this.input) {
      var service = services[this.input.name];
      this.service = service[this.checked];
    }
    return false;
  },

  submit: function(event)
  {
    // When clicking on submit button or pressing return key
    if (this.cursor > -1) {
        Event.stop(event);
    }
    return true;
  },

  checkInput: function(event)
  {
    if (!this.input) return false;
    if (this.sugchk) {
      if (!this.sugchk.checked) return false;
    }

    // check input params periodically
    if (this.input.value.length == 0) {
      this.MT = '';
      this.clear();
    }
    if (this.suggest == null) this.cursor = -1;
    if (this.input.value != this.MT && this.input.value.length > 0) {
      this.MT = this.input.value;
      this.disable();
      this.clear();
      // load ajax
      var request = new Ajax.Request(
        this.ajax_url,
        {
          method: 'get',
          parameters: 'search='+this.MT+'&num=10',//&sv='+this.service+'&fm='+this.format+'&cl='+this.client,
          onComplete: this.load.bindAsEventListener(this),
          onFailure:  this.clear.bindAsEventListener(this)
        }
      );
      this.cursor  = -1;
    }
    this.enable();
  },

  keyDown: function(event)
  {
    // check pressed key code
    var code = event.keyCode;
    switch (code) {
      case 17  : // Ctrl
      case 16  : // Shift
        Event.stop(event);
        break;
      case 38  : // ｢ｬ
        this.cursor = this.cursor - 1 >= -1 ? this.cursor - 1 : this.cursor;
        this.moveCursor();
        Event.stop(event);
        break;
      case 40  : // ｢ｭ
        this.cursor = this.cursor + 1 < this.cand_ary.length ? this.cursor + 1 : this.cursor;
        this.moveCursor();
        Event.stop(event);
        break;
      case 13  : // Return/Enter
        if (this.cursor > -1) {
          this.select();
          this.clear();
        } else {
          return true;
        }
        Event.stop(event);
        break;
      case 27  : // Esc
        this.cursor = -1;
        this.clear();
        break;
      case 229 : // Japanese Input Method
        break;
      default  : // Misc.
        break;
    }
    return true;
  },

  load: function(request)
  {
    // place suggest words after ajax
    if ($('suggest')) this.clear();
	//alert(request.responseText);
    var elem_ary = request.responseXML.documentElement.getElementsByTagName('element');
    if (elem_ary.length == 0) return true;
    var pos = Position.cumulativeOffset(this.input);
    this.suggest = document.createElement('ul'); // ul
    this.suggest.id = 'suggest';
    this.suggest.className = this.input.className == 'fullsize' ? 'suggest_full' : 'suggest_half'; //window style
    this.suggest.style.left = pos[0] + 'px';
    this.suggest.style.top  = (pos[1] + 18) + 'px';
    var cursor = 0;
    for (var i = 0; i < elem_ary.length; i++) {
      var cand_ary = elem_ary[i].getElementsByTagName('cand');
      if (cand_ary.length == 0) continue;
      var type = elem_ary[i].getAttribute('type');
      // Skip recommend when QGR cookie is 1
      if (type == 'recommend' && this.qgr_flag == '0') continue;
      if (type != 'suggest') {
        var head = document.createElement('li');
        head.className = 'head';
        head.innerHTML = suggest_types[type];
        this.suggest.appendChild(head);
      }
      for (var j = 0; j < cand_ary.length; j++) {
        var cand = new Array();
        var li = document.createElement('li');

        var word = cand_ary[j].getElementsByTagName('word');
        if (word[0].firstChild) cand['word'] = word[0].firstChild.nodeValue;
        else continue;
        if (type == 'narrow') cand['word'] = this.MT+' '+cand['word'];

        var html = cand_ary[j].getElementsByTagName('html');
        cand['html'] = html[0].firstChild ? html[0].firstChild.nodeValue : '';
        var div = document.createElement('div');
        div.className = 'normal';
        if (cand['html'] != '') {
          div.innerHTML = cand['word'] + '&nbsp;<img src="/img/top/hint.gif" width="16" height="16" alt=""/>';
        } else {
          div.innerHTML = cand['word'];
        }
        li.appendChild(div);

        Event.observe(div, 'mouseover', this.mouseOver.bindAsEventListener(this));
        Event.observe(div, 'click',     this.mouseClick.bindAsEventListener(this));
        cand['elem'] = div;
        this.cand_ary[cursor++] = cand;
        this.suggest.appendChild(li);
      }
    }
    document.body.appendChild(this.suggest);
    return true;
  },

  clear: function(event)
  {
    // clear suggest words
    if (this.suggest == null) return true;
    //alert(this.suggest);
    document.body.removeChild(this.suggest);
    this.suggest = null;
    this.cand_ary = new Array();
    if (this.extension == null) return true;
    document.body.removeChild(this.extension);
    this.extension = null;
    return true;
  },

  select: function()
  {
    // selecting on a suggeston word
    if (this.cursor < 0 || this.suggest == null) return true;
    var cand = this.cand_ary[this.cursor];
    this.input.value = cand['word'];
    return false;
  },

  resize: function(event)
  {
    // resizing window
    if (this.suggest == null) return;
    var pos = Position.cumulativeOffset(this.input);
    this.suggest.style.left = pos[0] + 'px';
    this.suggest.style.top  = (pos[1] + 18) + 'px';
    if (this.extension == null) return;
    cand = this.cand_ary[this.cursor];
    var pos = Position.cumulativeOffset(cand['elem']); 
    this.extension.style.left = (pos[0] + 165) + 'px';
    this.extension.style.top = pos[1] + 'px';
    return;
  },

  moveCursor: function()
  {
    // moving cursor
    var cand = null;
    if (this.suggest == null) return true;

    // remove selection
    for (var i = 0; i < this.cand_ary.length; i++) {
      cand = this.cand_ary[i];
      cand['elem'].className = 'normal';
    }

    // hide extension
    if (this.extension != null) {
      document.body.removeChild(this.extension);
      this.extension = null;
    }

    // show suggests
    if (this.cursor > -1) {
      cand = this.cand_ary[this.cursor];
      cand['elem'].className = 'selected';

	  var pos = Position.cumulativeOffset(cand['elem']);
	  //alert(pos[1]+','+this.suggest.scrollTop+','+this.suggest.scrollHeight+', top='+parseInt(this.suggest.style.top)+',bot='+this.suggest.offsetHeight);
	  if(pos[1] > this.suggest.scrollTop+parseInt(this.suggest.style.top)+this.suggest.offsetHeight-17)
		  this.suggest.scrollTop += 17; //this.suggest.scrollHeight;
	  else if(pos[1] < this.suggest.scrollTop+parseInt(this.suggest.style.top)+17)
		  this.suggest.scrollTop -= 17; // line height
    }

    // show extension
    if (cand['html'] != '') {
      this.extension = document.createElement('div');
      this.extension.id = 'extension';
      var pos = Position.cumulativeOffset(cand['elem']);
      this.extension.style.left = (pos[0] + 165) + 'px';
      this.extension.style.top  = pos[1] + 'px';
      this.extension.innerHTML  = cand['html'];
      document.body.appendChild(this.extension);
    }
    return true;
  },

  mouseOver: function(event)
  {
    // moving cursor to point a suggest word
    var cand = null;
    for (var i = 0; i < this.cand_ary.length; i++) {
      cand = this.cand_ary[i];
      if (cand['elem'] == Event.element(event)) {
        this.cursor = i;
        break;
      }
    }
    this.moveCursor();
    return false;
  },

  mouseClick: function(event)
  {
    // clicking on a suggested word
    var cand = null;
    for (var i = 0; i < this.cand_ary.length; i++) {
      cand = this.cand_ary[i];
      if (cand['elem'] == Event.element(event)) {
        this.cursor = i;
        break;
      }
    }
    this.select();
    this.clear();
    return false;
  },

  enable: function()
  {
    this.timerID = setTimeout(this.checkInput.bindAsEventListener(this), 50);
    return;
  },

  disable: function()
  {
    if (this.timerID != null) clearTimeout(this.timerID);
    this.timerID = null;
  }
};

var Hikaku_Suggest = Class.create();
Hikaku_Suggest.prototype = {
  initialize: function()
  {
    this.suggest  = null;           // 'ul' element to show suggests
    this.extend   = null;           // 'div' element to show extension of suggests
    this.cursor   = -1;             // cursor to point one of suggests
    this.cand_ary = new Array();    // array of suggests
    this.timerID  = null;           // timer ID
    this.MT       = '';             // copied value of MT input element
    this.input    = null;           // MT input element
    this.checked  = 'cond0';        // selected checkbox
    this.form     = $('hikaku_form'); // searchbod form element
    this.sugchk   = $('sugchk');
    if (this.sugchk) Event.observe(this.sugchk, 'click', this.enable.bindAsEventListener(this));
    this.ajax_url = '/Api/suggest';
    this.service  = null;
    this.format   = null;
    this.client   = null;
    this.qgr_flag = 1; 
    for (var i = 0; i < suggests.length; i++) {
      var inputs = this.form.getElementsByTagName('input');
      for (var j = 0; j < inputs.length; j++) {
        // set events for inputs
        if (inputs[j].name == suggests[i].input) {
          if (navigator.appName=='Microsoft Internet Explorer')
            Event.observe(inputs[j],  'keyup',    this.keyDown.bindAsEventListener(this));
          else
            Event.observe(inputs[j],  'keydown',  this.keyDown.bindAsEventListener(this));
          Event.observe(inputs[j],    'focus',    this.focus.bindAsEventListener(this));
          Event.observe(inputs[j],    'click',    this.clear.bindAsEventListener(this));
          if (i == 0) inputs[j].focus();  
        } 

        // set events for radio buttons
        if (i == 0) {
          for (var key in services[suggests[0].input]) {
            if (key == inputs[j].id) {
              Event.observe(inputs[j], 'click',  function(event) {
                this.checked = Event.element(event).id;
                this.switchModule();
              }.bindAsEventListener(this));
            }
          }
          if (inputs[j].checked) this.checked = inputs[j].id;
        }
      }
    }

    this.switchModule();
    Event.observe(document.body, 'click',    this.clear.bindAsEventListener(this));
    Event.observe(this.form,     'submit',   this.submit.bindAsEventListener(this));
    Event.observe(window,        'resize',   this.resize.bindAsEventListener(this));
    this.enable();
    return;
  },

  focus: function(event)
  {
    var input = Event.element(event);
    for (var i = 0; i < suggests.length; i++) {
      if (input.name == suggests[i].input) break;
    }
    if (i < suggests.length) {
      this.MT      = input.value;
      this.input   = input;
      this.switchModule();
      this.format  = 'xml';
      this.client  = 'bitem';//suggests[i].client;
    }
    Event.stop(event);
    return false;
  },
  
  switchModule: function()
  {
    if (this.input) {
      var service = services[this.input.name];
      this.service = service[this.checked];
    }
    return false;
  },

  submit: function(event)
  {
    // When clicking on submit button or pressing return key
    if (this.cursor > -1) {
        Event.stop(event);
    }
    return true;
  },

  checkInput: function(event)
  {
    if (!this.input) return false;
    if (this.sugchk) {
      if (!this.sugchk.checked) return false;
    }

    // check input params periodically
    if (this.input.value.length == 0) {
      this.MT = '';
      this.clear();
    }
    if (this.suggest == null) this.cursor = -1;
    if (this.input.value != this.MT && this.input.value.length > 0) {
      this.MT = this.input.value;
      this.disable();
      this.clear();
      // load ajax
      var request = new Ajax.Request(
        this.ajax_url,
        {
          method: 'get',
          parameters: 'search='+this.MT+'&num=10',//&sv='+this.service+'&fm='+this.format+'&cl='+this.client,
          onComplete: this.load.bindAsEventListener(this),
          onFailure:  this.clear.bindAsEventListener(this)
        }
      );
      this.cursor  = -1;
    }
    this.enable();
  },

  keyDown: function(event)
  {
    // check pressed key code
    var code = event.keyCode;
    switch (code) {
      case 17  : // Ctrl
      case 16  : // Shift
        Event.stop(event);
        break;
      case 38  : // ｢ｬ
        this.cursor = this.cursor - 1 >= -1 ? this.cursor - 1 : this.cursor;
        this.moveCursor();
        Event.stop(event);
        break;
      case 40  : // ｢ｭ
        this.cursor = this.cursor + 1 < this.cand_ary.length ? this.cursor + 1 : this.cursor;
        this.moveCursor();
        Event.stop(event);
        break;
      case 13  : // Return/Enter
        if (this.cursor > -1) {
          this.select();
          this.clear();
        } else {
          return true;
        }
        Event.stop(event);
        break;
      case 27  : // Esc
        this.cursor = -1;
        this.clear();
        break;
      case 229 : // Japanese Input Method
        break;
      default  : // Misc.
        break;
    }
    return true;
  },

  load: function(request)
  {
    // place suggest words after ajax
    if ($('suggest')) this.clear();
	//alert(request.responseText);
    var elem_ary = request.responseXML.documentElement.getElementsByTagName('element');
    if (elem_ary.length == 0) return true;
    var pos = Position.cumulativeOffset(this.input);
    this.suggest = document.createElement('ul'); // ul
    this.suggest.id = 'suggest';
    this.suggest.className = this.input.className == 'fullsize' ? 'suggest_full' : 'suggest_half'; //window style
    this.suggest.style.left = pos[0] + 'px';
    this.suggest.style.top  = (pos[1] + 18) + 'px';
    var cursor = 0;
    for (var i = 0; i < elem_ary.length; i++) {
      var cand_ary = elem_ary[i].getElementsByTagName('cand');
      if (cand_ary.length == 0) continue;
      var type = elem_ary[i].getAttribute('type');
      // Skip recommend when QGR cookie is 1
      if (type == 'recommend' && this.qgr_flag == '0') continue;
      if (type != 'suggest') {
        var head = document.createElement('li');
        head.className = 'head';
        head.innerHTML = suggest_types[type];
        this.suggest.appendChild(head);
      }
      for (var j = 0; j < cand_ary.length; j++) {
        var cand = new Array();
        var li = document.createElement('li');

        var word = cand_ary[j].getElementsByTagName('word');
        if (word[0].firstChild) cand['word'] = word[0].firstChild.nodeValue;
        else continue;
        if (type == 'narrow') cand['word'] = this.MT+' '+cand['word'];

        var html = cand_ary[j].getElementsByTagName('html');
        cand['html'] = html[0].firstChild ? html[0].firstChild.nodeValue : '';
        var div = document.createElement('div');
        div.className = 'normal';
        if (cand['html'] != '') {
          div.innerHTML = cand['word'] + '&nbsp;<img src="/img/top/hint.gif" width="16" height="16" alt=""/>';
        } else {
          div.innerHTML = cand['word'];
        }
        li.appendChild(div);

        Event.observe(div, 'mouseover', this.mouseOver.bindAsEventListener(this));
        Event.observe(div, 'click',     this.mouseClick.bindAsEventListener(this));
        cand['elem'] = div;
        this.cand_ary[cursor++] = cand;
        this.suggest.appendChild(li);
      }
    }
    document.body.appendChild(this.suggest);
    return true;
  },

  clear: function(event)
  {
    // clear suggest words
    if (this.suggest == null) return true;
    //alert(this.suggest);
    document.body.removeChild(this.suggest);
    this.suggest = null;
    this.cand_ary = new Array();
    if (this.extension == null) return true;
    document.body.removeChild(this.extension);
    this.extension = null;
    return true;
  },

  select: function()
  {
    // selecting on a suggeston word
    if (this.cursor < 0 || this.suggest == null) return true;
    var cand = this.cand_ary[this.cursor];
    this.input.value = cand['word'];
    return false;
  },

  resize: function(event)
  {
    // resizing window
    if (this.suggest == null) return;
    var pos = Position.cumulativeOffset(this.input);
    this.suggest.style.left = pos[0] + 'px';
    this.suggest.style.top  = (pos[1] + 18) + 'px';
    if (this.extension == null) return;
    cand = this.cand_ary[this.cursor];
    var pos = Position.cumulativeOffset(cand['elem']); 
    this.extension.style.left = (pos[0] + 165) + 'px';
    this.extension.style.top = pos[1] + 'px';
    return;
  },

  moveCursor: function()
  {
    // moving cursor
    var cand = null;
    if (this.suggest == null) return true;

    // remove selection
    for (var i = 0; i < this.cand_ary.length; i++) {
      cand = this.cand_ary[i];
      cand['elem'].className = 'normal';
    }

    // hide extension
    if (this.extension != null) {
      document.body.removeChild(this.extension);
      this.extension = null;
    }

    // show suggests
    if (this.cursor > -1) {
      cand = this.cand_ary[this.cursor];
      cand['elem'].className = 'selected';

	  var pos = Position.cumulativeOffset(cand['elem']);
	  //alert(pos[1]+','+this.suggest.scrollTop+','+this.suggest.scrollHeight+', top='+parseInt(this.suggest.style.top)+',bot='+this.suggest.offsetHeight);
	  if(pos[1] > this.suggest.scrollTop+parseInt(this.suggest.style.top)+this.suggest.offsetHeight-17)
		  this.suggest.scrollTop += 17; //this.suggest.scrollHeight;
	  else if(pos[1] < this.suggest.scrollTop+parseInt(this.suggest.style.top)+17)
		  this.suggest.scrollTop -= 17; // line height
    }

    // show extension
    if (cand['html'] != '') {
      this.extension = document.createElement('div');
      this.extension.id = 'extension';
      var pos = Position.cumulativeOffset(cand['elem']);
      this.extension.style.left = (pos[0] + 165) + 'px';
      this.extension.style.top  = pos[1] + 'px';
      this.extension.innerHTML  = cand['html'];
      document.body.appendChild(this.extension);
    }
    return true;
  },

  mouseOver: function(event)
  {
    // moving cursor to point a suggest word
    var cand = null;
    for (var i = 0; i < this.cand_ary.length; i++) {
      cand = this.cand_ary[i];
      if (cand['elem'] == Event.element(event)) {
        this.cursor = i;
        break;
      }
    }
    this.moveCursor();
    return false;
  },

  mouseClick: function(event)
  {
    // clicking on a suggested word
    var cand = null;
    for (var i = 0; i < this.cand_ary.length; i++) {
      cand = this.cand_ary[i];
      if (cand['elem'] == Event.element(event)) {
        this.cursor = i;
        break;
      }
    }
    this.select();
    this.clear();
    return false;
  },

  enable: function()
  {
    this.timerID = setTimeout(this.checkInput.bindAsEventListener(this), 50);
    return;
  },

  disable: function()
  {
    if (this.timerID != null) clearTimeout(this.timerID);
    this.timerID = null;
  }
};
