/*
 *
 *  Ajax Autocomplete for Prototype, version 1.0.4
 *  (c) 2010 Tomas Kirda
 *
 *  Ajax Autocomplete for Prototype is freely distributable under the terms of an MIT-style license.
 *  For details, see the web site: http://www.devbridge.com/projects/autocomplete/
 *
 */

var lang=1;
function InFarsi (str) {
  var len;
  var i;
  var ch = "";
  var uCode;
  var rc;

lang=1;
  rc = false; //English

  len = str.length;
  for (i=0; i < len; i++) {
    ch = str.substring(i, i+1)
    uCode=ch.charCodeAt(0);
    if (uCode >= 0x0600) {
      rc = true; //Farsi
lang=2;
      break;
    }
  }

  return (rc);
}




function formatForDB(inputStr) {
var rc = "";
var ch;
var len;

  len = inputStr.length;

  if (len < 1) {
    return rc;
  }

  rc = "";

  for (i=0; i < len; i++) {
    ch = inputStr.substring(i, i+1)
    uCode=ch.charCodeAt(0);

    switch (uCode) {
         case 0x06f0: //zero
           rc = rc + String.fromCharCode(48);
           break;

         case 0x06f1: //one
           rc = rc + String.fromCharCode(49);
           break;

         case 0x06f2: //two
           rc = rc + String.fromCharCode(50);
           break;

         case 0x06f3: //three
           rc = rc + String.fromCharCode(51);
           break;

         case 0x06f4: //four
           rc = rc + String.fromCharCode(52);
           break;

         case 0x06f5: //five
           rc = rc + String.fromCharCode(53);
           break;

         case 0x06f6: //six
           rc = rc + String.fromCharCode(54);
           break;

         case 0x06f7: //seven
           rc = rc + String.fromCharCode(55);
           break;

         case 0x06f8: //eight
           rc = rc + String.fromCharCode(56);
           break;

         case 0x06f9: //nine
           rc = rc + String.fromCharCode(57);
           break;

         case 0x061f: //Farsi question mark
           rc = rc + String.fromCharCode(88);
           break;

//         case 0x0640: //Farsi keshideh
//           rc = rc + String.fromCharCode(89);
//           break;

         case 0x0622: //AA bA kola
           rc = rc + String.fromCharCode(90);
           break;

         case 0x0627: //alef
//           rc = rc + String.fromCharCode(91);
           rc = rc + "MyAlef";
           break;

         case 0x0626: //hamzeh chasbAn
//           rc = rc + String.fromCharCode(92);
           rc = rc + "MyHamzehChasban";
           break;

         case 0x0621: //hamzeh tanhA
//           rc = rc + String.fromCharCode(93);
           rc = rc + "MyHamzehTanha";
           break;

         case 0x0628: //be
//           rc = rc + String.fromCharCode(94);
           rc = rc + "MyBe";
           break;

         case 0x067e: //pe
           rc = rc + String.fromCharCode(95);
           break;

         case 0x062a: //te
//           rc = rc + String.fromCharCode(96);
           rc = rc + "MyTe";
           break;

         case 0x062b: //ceh
           rc = rc + String.fromCharCode(97);
           break;

         case 0x062c: //jim
           rc = rc + String.fromCharCode(98);
           break;

         case 0x0686: //che
           rc = rc + String.fromCharCode(99);
           break;

         case 0x062d: //heh
           rc = rc + String.fromCharCode(100);
           break;

         case 0x062e: //khe
           rc = rc + String.fromCharCode(101);
           break;

         case 0x062f: //daal
           rc = rc + String.fromCharCode(102);
           break;

         case 0x0630: //zaal
           rc = rc + String.fromCharCode(103);
           break;

         case 0x0631: //re
           rc = rc + String.fromCharCode(104);
           break;

         case 0x0632: //ze
           rc = rc + String.fromCharCode(105);
           break;

         case 0x0698: //zhe
           rc = rc + String.fromCharCode(106);
           break;

         case 0x0633: //sin
           rc = rc + String.fromCharCode(107);
           break;

         case 0x0634: //shin
           rc = rc + String.fromCharCode(108);
           break;

         case 0x0635: //saad
           rc = rc + String.fromCharCode(109);
           break;

         case 0x0636: //zaad
           rc = rc + String.fromCharCode(110);
           break;

         case 0x0637: //taa
           rc = rc + String.fromCharCode(111);
           break;

         case 0x0638: //zaa
           rc = rc + String.fromCharCode(112);
           break;

         case 0x0639: //ain
           rc = rc + String.fromCharCode(113);
           break;

         case 0x063a: //ghain
           rc = rc + String.fromCharCode(114);
           break;

         case 0x0641: //fe
           rc = rc + String.fromCharCode(115);
           break;

         case 0x0642: //ghaaf
           rc = rc + String.fromCharCode(116);
           break;

         case 0x06a9: //kaaf
           rc = rc + String.fromCharCode(117);
           break;

         case 0x0643: //kaaf
           rc = rc + String.fromCharCode(117);
           break;

         case 0x06af: //gaaf
           rc = rc + String.fromCharCode(118);
           break;

         case 0x0644: //laam
           rc = rc + String.fromCharCode(119);
           break;

         case 0x0645: //mim 1605
           rc = rc + String.fromCharCode(120);
           break;

         case 0x0646: //noon 1606
           rc = rc + String.fromCharCode(121);
           break;

         case 0x0648: //vaav
           rc = rc + String.fromCharCode(122);
           break;

         case 0x0647: //he
//           rc = rc + String.fromCharCode(123);
           rc = rc + "MyHe";
           break;

         case 0x0649: //yeh
//           rc = rc + String.fromCharCode(124);
           rc = rc + "MyYe";
           break;

         case 0x064a: //yeh dot 1610
//           rc = rc + String.fromCharCode(124);
           rc = rc + "MyYe";
           break;

         case 0x06cc: //yeh 1740
//           rc = rc + String.fromCharCode(124);
           rc = rc + "MyYe";
           break;

         case 65: //A
           rc = rc + String.fromCharCode(65);
           break;

         case 66: //B
           rc = rc + String.fromCharCode(66);
           break;

         case 67: //C
           rc = rc + String.fromCharCode(67);
           break;

         case 68: //D
           rc = rc + String.fromCharCode(68);
           break;

         case 69: //E
           rc = rc + String.fromCharCode(69);
           break;

         case 72: //H
           rc = rc + String.fromCharCode(70);
           break;

         case 75: //K
           rc = rc + String.fromCharCode(71);
           break;

         case 79: //O
           rc = rc + String.fromCharCode(72);
           break;

         case 85: //U
           rc = rc + String.fromCharCode(73);
           break;

         case 86: //V
           rc = rc + String.fromCharCode(74);
           break;

         case 94: //^
           rc = rc + String.fromCharCode(77);
           break;

         case 111: //o
           rc = rc + String.fromCharCode(80);
           break;

         case 126: //~
           rc = rc + String.fromCharCode(85);
           break;

         default:
           if (uCode < 128) {
             rc = rc + ch;
           }
      }

  }

 
  return rc;
}		



var Autocomplete = function(el, options){
  this.el = $(el);
  this.id = this.el.identify();
  this.el.setAttribute('autocomplete','off');
  this.suggestions = [];
  this.data = [];
  this.badQueries = [];
  this.selectedIndex = -1;
  this.currentValue = this.el.value;
  this.intervalId = 0;
  this.cachedResponse = [];
  this.instanceId = null;
  this.onChangeInterval = null;
  this.ignoreValueChange = false;
  this.serviceUrl = options.serviceUrl;
  this.options = {
    autoSubmit:false,
    minChars:1,
    maxHeight:300,
    deferRequestBy:0,
    width:0,
    container:null
  };
  if(options){ Object.extend(this.options, options); }
  if(Autocomplete.isDomLoaded){
    this.initialize();
  }else{
    Event.observe(document, 'dom:loaded', this.initialize.bind(this), false);
  }
};

Autocomplete.instances = [];
Autocomplete.isDomLoaded = false;

Autocomplete.getInstance = function(id){
  var instances = Autocomplete.instances;
  var i = instances.length;
  while(i--){ if(instances[i].id === id){ return instances[i]; }}
};

Autocomplete.highlight = function(value, re){
  return value.replace(re, function(match){return '<strong>' + match + '<\/strong>' });
};

Autocomplete.prototype = {

  killerFn: null,

  initialize: function() {
    var me = this;
    this.killerFn = function(e) {
      if (!$(Event.element(e)).up('.autocomplete')) {
        me.killSuggestions();
        me.disableKillerFn();
      }
    } .bindAsEventListener(this);

    if (!this.options.width) { this.options.width = this.el.getWidth(); }

    var div = new Element('div', { style: 'position:absolute;' });
    div.update('<div class="autocomplete-w1"><div class="autocomplete-w2"><div class="autocomplete" id="Autocomplete_' + this.id + '" style="display:none; width:' + this.options.width + 'px;"></div></div></div>');

    this.options.container = $(this.options.container);
    if (this.options.container) {
      this.options.container.appendChild(div);
      this.fixPosition = function() { };
    } else {
      document.body.appendChild(div);
    }

    this.mainContainerId = div.identify();
    this.container = $('Autocomplete_' + this.id);
    this.fixPosition();
    
    Event.observe(this.el, window.opera ? 'keypress':'keydown', this.onKeyPress.bind(this));
    Event.observe(this.el, 'keyup', this.onKeyUp.bind(this));
    Event.observe(this.el, 'blur', this.enableKillerFn.bind(this));
    Event.observe(this.el, 'focus', this.fixPosition.bind(this));

    this.container.setStyle({ maxHeight: this.options.maxHeight + 'px' });
    this.instanceId = Autocomplete.instances.push(this) - 1;
  },

  fixPosition: function() {
    var offset = this.el.cumulativeOffset();
    $(this.mainContainerId).setStyle({ top: (offset.top + this.el.getHeight()) + 'px', left: offset.left + 'px' });
  },

  enableKillerFn: function() {
    Event.observe(document.body, 'click', this.killerFn);
  },

  disableKillerFn: function() {
    Event.stopObserving(document.body, 'click', this.killerFn);
  },

  killSuggestions: function() {
    this.stopKillSuggestions();
    this.intervalId = window.setInterval(function() { this.hide(); this.stopKillSuggestions(); } .bind(this), 300);
  },

  stopKillSuggestions: function() {
    window.clearInterval(this.intervalId);
  },

  onKeyPress: function(e) {
if (InFarsi(this.currentValue)) {
}

    if (!this.enabled) { return; }
    // return will exit the function
    // and event will not fire

    switch (e.keyCode) {
      case Event.KEY_ESC:
        this.el.value = this.currentValue;
        this.hide();
        break;
      case Event.KEY_TAB:
      case Event.KEY_RETURN:
        if (this.selectedIndex === -1) {
          this.hide();
          return;
        }
        this.select(this.selectedIndex);
        if (e.keyCode === Event.KEY_TAB) { return; }
        break;
      case Event.KEY_UP:
        this.moveUp();
        break;
      case Event.KEY_DOWN:
        this.moveDown();
        break;
      default:
        return;
    }
    Event.stop(e);
  },

  onKeyUp: function(e) {
    switch (e.keyCode) {
      case Event.KEY_UP:
      case Event.KEY_DOWN:
        return;
    }
    clearInterval(this.onChangeInterval);
    if (this.currentValue !== this.el.value) {
      if (this.options.deferRequestBy > 0) {
        // Defer lookup in case when value changes very quickly:
        this.onChangeInterval = setInterval((function() {
          this.onValueChange();
        }).bind(this), this.options.deferRequestBy);
      } else {
        this.onValueChange();
      }
    }
  },

  onValueChange: function() {
    clearInterval(this.onChangeInterval);
    this.currentValue = this.el.value;
    this.selectedIndex = -1;
    if (this.ignoreValueChange) {
      this.ignoreValueChange = false;
      return;
    }
    if (this.currentValue === '' || this.currentValue.length < this.options.minChars) {
      this.hide();
    } else {
      this.getSuggestions();
    }
  },

  getSuggestions: function() {
    var cr = this.cachedResponse[this.currentValue];
    if (cr && Object.isArray(cr.suggestions)) {
      this.suggestions = cr.suggestions;
      this.data = cr.data;
      this.suggest();
    } else if (!this.isBadQuery(this.currentValue)) {

if (InFarsi(this.currentValue)) {
//  this.currentValue = "{<]:" + formatForDB(this.currentValue);
}


  this.currentValue = encodeURIComponent(this.currentValue);
  this.currentValue = this.currentValue.replace(new RegExp("%", 'g'),"{}");




      new Ajax.Request(this.serviceUrl, {
        parameters: { query: this.currentValue },
        onComplete: this.processResponse.bind(this),
        method: 'get'
      });
    }
  },

  isBadQuery: function(q) {
    var i = this.badQueries.length;
    while (i--) {
      if (q.indexOf(this.badQueries[i]) === 0) { return true; }
    }
    return false;
  },

  hide: function() {
    this.enabled = false;
    this.selectedIndex = -1;
    this.container.hide();
  },

  suggest: function() {
    if (this.suggestions.length === 0) {
      this.hide();
      return;
    }
    var content = [];
    var re = new RegExp('\\b' + this.currentValue.match(/\w+/g).join('|\\b'), 'gi');
    this.suggestions.each(function(value, i) {
var tagf="";
if (lang===2) {
  tagf=' style="text-align:right;" dir="rtl" ';
}
else {
  tagf=' style="text-align:left;" dir="ltr" ';
}
      content.push((this.selectedIndex === i ? '<class="selected"'+lang : '<div '+tagf), ' title="', value, '" onclick="Autocomplete.instances[', this.instanceId, '].select(', i, ');" onmouseover="Autocomplete.instances[', this.instanceId, '].activate(', i, ');">', Autocomplete.highlight(value, re), '</div>');
    } .bind(this));
    this.enabled = true;
    this.container.update(content.join('')).show();
  },

  processResponse: function(xhr) {
    var response;
    try {
      response = xhr.responseText.evalJSON();
      if (!Object.isArray(response.data)) { response.data = []; }
    } catch (err) { return; }
    this.cachedResponse[response.query] = response;
    if (response.suggestions.length === 0) { this.badQueries.push(response.query); }
    if (response.query === this.currentValue) {
      this.suggestions = response.suggestions;
      this.data = response.data;
      this.suggest(); 
    }
  },

  activate: function(index) {
    var divs = this.container.childNodes;
    var activeItem;
    // Clear previous selection:
    if (this.selectedIndex !== -1 && divs.length > this.selectedIndex) {
      divs[this.selectedIndex].className = '';
    }
    this.selectedIndex = index;
    if (this.selectedIndex !== -1 && divs.length > this.selectedIndex) {
      activeItem = divs[this.selectedIndex];
      activeItem.className = 'selected' + lang;
    }
    return activeItem;
  },

  deactivate: function(div, index) {
    div.className = '';
    if (this.selectedIndex === index) { this.selectedIndex = -1; }
  },

  select: function(i) {
    var selectedValue = this.suggestions[i];
    if (selectedValue) {
      this.el.value = selectedValue;
      if (this.options.autoSubmit && this.el.form) {
        this.el.form.submit();
      }
      this.ignoreValueChange = true;
      this.hide();
      this.onSelect(i);
    }
  },

  moveUp: function() {
    if (this.selectedIndex === -1) { return; }
    if (this.selectedIndex === 0) {
      this.container.childNodes[0].className = '';
      this.selectedIndex = -1;
      this.el.value = this.currentValue;
      return;
    }
    this.adjustScroll(this.selectedIndex - 1);
  },

  moveDown: function() {
    if (this.selectedIndex === (this.suggestions.length - 1)) { return; }
    this.adjustScroll(this.selectedIndex + 1);
  },

  adjustScroll: function(i) {
    var container = this.container;
    var activeItem = this.activate(i);
    var offsetTop = activeItem.offsetTop;
    var upperBound = container.scrollTop;
    var lowerBound = upperBound + this.options.maxHeight - 25;
    if (offsetTop < upperBound) {
      container.scrollTop = offsetTop;
    } else if (offsetTop > lowerBound) {
      container.scrollTop = offsetTop - this.options.maxHeight + 25;
    }
    this.el.value = this.suggestions[i];
  },

  onSelect: function(i) {
    (this.options.onSelect || Prototype.emptyFunction)(this.suggestions[i], this.data[i]);
  }

};

Event.observe(document, 'dom:loaded', function(){ Autocomplete.isDomLoaded = true; }, false);

