var ESC_CODE=27;
var ENTER_CODE=13;
var UP_CODE=38;
var DOWN_CODE=40;

var MIN_WIDTH=150;
var MAX_HEIGHT=200;

var suppress_blur = false;
var selected_index = -1;
var lis;

function initAutoCompletes(scope) {
  var inputs=getElementsByClass('suggest_[a-zA-Z0-9]+',scope,'input');
  for(var i=0;i<inputs.length;i++){
    initAutoComplete(
      inputs[i],
      scope
    );
  }//for
}//initAutoCompletes

function initAutoComplete(input,init_scope){
  var ul=document.createElement('UL');
  document.body.appendChild(ul);
  if(init_scope){
    var className=hasClass(input,'suggest_[a-zA-Z0-9]+').replace('suggest_','suggest ');
    var uls=getElementsByClass(className,init_scope,'ul');
    if(uls.length){
      init_lis=uls[0].getElementsByTagName('LI');
      for(var i=0;i<init_lis.length;i++)
        ul.appendChild(init_lis[i].cloneNode(true));
    }//if
  }//if
  initSuggestLis(ul,input);
  ul.className='suggest';
  ul.style.position='absolute';
  ul.style.display='none';
  if (input.offsetWidth == 0 && $('overlay')) { 
    ul.style.width = '275px'; 
  }else{
    ul.style.width=(input.offsetWidth<MIN_WIDTH?MIN_WIDTH:input.offsetWidth)-2+'px';
  }
  if (ul.style.maxHeight != undefined)
    ul.style.maxHeight=MAX_HEIGHT+'px';
  else
    ul.style.height=MAX_HEIGHT+'px';
  ul.style.whiteSpace='nowrap';
  ul.style.overflow='auto';
  try{
    ul.style.overflowX='hidden';
  } catch(e){
    //do nothing
  }//try
  ul.style.margin = '0';
  input.onkeyup=function(e){
    mousemove_enabled = true;
    var keyCode=getKeyCode(e);
    if(keyCode==ENTER_CODE ||
       keyCode==ESC_CODE ||
       keyCode==DOWN_CODE ||
       keyCode==UP_CODE)
      return;
    filterList(ul,input.value);
    if(hasClass(input,'ajax'))
      reloadList(ul,input,input.value);
    if(input.value){
      showList(ul,input);
    } else {
      hideList(ul,input);
    }//if
  }//keyup
  
  // Separate function is for IE that doesn't handle UP and DOWN in keypress
  var processCursorKeys = function(keyCode) {
    showList(ul,input);
    var li = moveListSelection(ul,keyCode==DOWN_CODE?'down':'up');
    mousemove_enabled = false;
    if (li.offsetTop < ul.scrollTop)
      ul.scrollTop = li.offsetTop;
    else if (li.offsetTop + li.offsetHeight > ul.scrollTop + ul.offsetHeight)
      ul.scrollTop = li.offsetTop + li.offsetHeight - ul.offsetHeight;
    // mouse moves are enabled at keyup
  }//processCursorKeys
  
  input.onkeypress = function(e){
    var keyCode=getKeyCode(e);
    if(keyCode==ESC_CODE){
      hideList(ul,input);
    } else if(keyCode==DOWN_CODE || keyCode==UP_CODE){
      processCursorKeys(keyCode);
    } else if(keyCode==ENTER_CODE){
      var li=selectedItem(ul);
      if(li){
        input.value=liValue(li);
      } else {
        if(hasClass(input,'strict'))
          input.value='';
      }//if
      var open = ul.offsetHeight > 0;
      hideList(ul,input);
      if (open) {
        if(e && e.preventDefault) {
          e.preventDefault();
          e.preventEnter = true;
        }
        return false;
      }//
    }//if
  }//keypress
  input.onkeydown = function(e) {
    if (e) 
      return true; // serve only IE here
    var keyCode=getKeyCode(e);
    if (keyCode==DOWN_CODE || keyCode==UP_CODE){
      processCursorKeys(keyCode);
    }//if
  }//onkeydown
  input.onblur=function(e){
    if (suppress_blur) {
      suppress_blur = false;
      input.focus();
      return;
    }//if
    suppress_blur = false;
    if(hasClass(input,'strict')){
      var li=selectedItem(ul);
      if(li)
        input.value=liValue(li);
      else
        input.value='';
    }//if
    hideList(ul,input);
  }//blur
  input.onclick=function(e){
    if(ul.offsetHeight)
      hideList(ul,input);
    else
      showList(ul,input);
  }//click
  ul.onmousedown = function(e) {
    if (window.event && window.event.srcElement == ul)
      suppress_blur = true;
  }
}//initAutoComplete

//Изменениях в этой функции надо не забывать дублировать в utils.py
function normalizeTitle(title){
  title=title.toLowerCase();
  title=title.replace('ё','е');
  safe_title=title // safe_title can't be empty since nothing has been removed yet
  title=title.replace(/\bthe\b/,'');
  title=title.replace(/[\,\.\(\)\-\!\'\"\`\?\_\:\;\$\]\[\#\/]/,'');
  title=title.replace(/\s+/,'');
  return title!=''?title:safe_title;
}//normalizeTitle

function liValue(li){
  if(li.firstChild)
    return li.firstChild.nodeValue.replace(/[\n\s]+$/,'');
  else
    return '';
}//liValue

function showList(ul,input){
  ul.style.display = 'block';
  ul.style.left = elLeft(input) + 'px';
  ul.style.top = elTop(input) + input.offsetHeight - 1 + 'px';
}//showList

function hideList(ul,input){
  ul.style.display='none';
}//hideList

function filterList(ul,value){
  lis = ul.getElementsByTagName('LI');
  for(var i=0;i<lis.length;i++){
    if(normalizeTitle(liValue(lis[i])).indexOf(normalizeTitle(value))==0)
      lis[i].style.display='';
    else {
      lis[i].style.display='none';
    }//if
  }//for
  if(hasClass(ul,'strict')){
    if(!selectedItem(ul))
      moveListSelection(ul,'down');
  }//if
}//filterList

function selectedItem(ul){
  var lis=getElementsByClass('selected',ul,'LI');
  if(lis.length)
    return lis[0];
  else
    return null;
}//selectedItem

function clearListSelection(ul){
  var li=selectedItem(ul);
  if(li)
    removeClass(li,'selected');
}//clearListSelection

function moveListSelection(ul,direction){
  var old_index = removeSelection(lis);
  var index = old_index;
  var inc = (direction == 'down' ? 1 : -1);
  do {
    index += inc;
    if(index < 0)
      index = lis.length - 1;
    if(index >= lis.length)
      index = 0;
  } while (index != old_index && !lis[index].offsetHeight);
  if (index == old_index)
    return;
  setSelection(lis, index);
  return lis[index];
}//moveListSelection

function setSelection(lis, index) {
  addClass(lis[index], 'selected');
  selected_index = index;
}//setSelection

function removeSelection(lis){
  var index = selected_index;
  if(selected_index >= 0) {
    removeClass(lis[index], 'selected');
    selected_index = -1;
  }//if
  return index;
}//removeSelection

var request=null;
var requestTimeout=null;

function reloadList(ul,input,value){
  clearTimeout(requestTimeout);
  requestTimeout=setTimeout(function(){
    if(request){
      request.abort();
      request=null;
    }//if
    addClass(ul,'loading');
    request=createRequest();
    request.onreadystatechange=function(){
      if(request.readyState!=4)
        return;
      removeClass(ul,'loading');
      if(request.status!=200)
        return;
      selected=selectedItem(ul);
      if(selected)
        var old_value=liValue(selected);
      else
        var old_value='';
      ul.innerHTML=request.responseText;
      lis = ul.getElementsByTagName('LI');
      if(lis.length){
        var i=0;
        while(i<lis.length && liValue(lis[i])!=old_value)
          i++;
        if(i<lis.length)
          setSelection(lis, i);
        else {
          if(hasClass(input,'strict'))
            setSelection(lis, 0);
        }//if
      }//if
      initSuggestLis(ul,input);
      request=null;
    }//onreadystatechange
    field=hasClass(input,'suggest_[a-zA-Z0-9]+').replace('suggest_','');
    var request_uri = '/suggest/'+field+'/?value='+input.value;
    if ($('id_artist') && $('id_artist').value !='') {
      request_uri += '&artist=' + $('id_artist').value;
    }
    request.open('GET',encodeURI(request_uri));
    request.send(null);
  },500);
}//reloadList

var mousemove_enabled = true;

function initSuggestLis(ul,input){
  lis = ul.getElementsByTagName('LI');
  for(var i=0;i<lis.length;i++){
    lis[i].onmousedown=function(){
      input.value=liValue(this);
    }//onmousedown
    lis[i].onmouseover = function() {
      var index = i;
      return function(){
        if (!mousemove_enabled)
          return;
        removeSelection(lis);
        setSelection(lis, index);
      }//onmouseover
    }();
  }//for
}//initSuggestLis
