/* Constants */
var URL_BAD_BROWSER         = 'badbrowser.php';
var URL_SEARCH_SIMPLE       = 'search.php';
var URL_SEARCH_NEIGHBORHOOD = 'search_neighborhood.php';
var URL_UPDATE_QUERY        = 'update_query.php';
var URL_SAVE_QUERY          = 'save_query.php';

/* State variables */
var cur_species;
var do_autohide;
var cur_searchmode;
var query_frame_form;

/*******************************************************/
/*   Utility functions                                 */
/*******************************************************/

function html_entities_decode(str)
{
  return str;

  str = str.replace(/&lt;/g,"<");
  str = str.replace(/&gt;/g,">");
  str = str.replace(/&quot;/g,"\"");
  str = str.replace(/&apos;/g,"'");
  str = str.replace(/&amp;/g,"&");

  return str;
}

function trim(str)
{
  return str.replace(/^\s*|\s*$/g,"");
}

function join(delim, list)
{
  var result = "";

  for(var i=0 ; i < list.length ; ++i)
  {
    if(i)
      result += delim;
    result += list[i];
  }

  return result;
}

function setVisibility(obj, isShown)
{
  obj.style.display = isShown ? 'block' : 'none';
}

function getVisibility(obj, isShown)
{
  return (obj.style.display != '' && obj.style.display != 'none');
}

/*******************************************************/
/*   Progress bar                                      */
/*******************************************************/

var prog_parts;
var cur_prog = 0;

function set_progress(frac)
{
  var obj = document.getElementById('progressbar');
  if(!obj)
    return;

  var w = frac * 480;
  obj.style.clip = 'rect(0px,' + w + 'px,21px,0px)';
}


/*******************************************************/
/*   Event handlers                                    */
/*******************************************************/

function handle_load()
{
  init_debug_console();
  init_xml_fetchers();

  var autohide_obj = document.getElementById('autohide');
  var autoshow_obj = document.getElementById('autoshow');
  if(do_autohide && autohide_obj)
    setVisibility(autohide_obj, false);
  if(do_autohide && autoshow_obj)
    setVisibility(autoshow_obj, true);

  handle_searchmode();
  update_query_frames();
}

function handle_queryframe_load(frm)
{
  query_frame_form = frm;
  update_clear_state();

  var show_preview = query_frame_form ? true : false;

  setVisibility(document.getElementById('query_buttons'), show_preview);
  setVisibility(document.getElementById('query_preview'), show_preview);
}

function find_option_idx(needle, haystack, default_value)
{
  for(var i=0 ; i < haystack.options.length ; ++i)
  {
    if(haystack.options[i].value == needle)
    {
      return i;
    }
  }

  return undefined;
}

function handle_change_species(obj)
{
  var cur_species_idx = find_option_idx(cur_species, obj);
  var new_species_idx = obj.selectedIndex;

  if(new_species_idx == 0)
  {
    obj.selectedIndex = cur_species_idx;
    return;
  }

  if(new_species_idx == cur_species_idx)
  {
    return;
  }

  if(cur_species_idx != 0)
  {
    if(!confirm("Changing the species will clear your query.  Are you sure you want to continue?"))
    {
      obj.selectedIndex = cur_species_idx;
      return;
    }
  }

  document.f['change_species'].value = "1";
  document.f.submit();
}

function handle_resolve()
{
  document.f.submit();
}

function handle_delete(gi)
{
  document.f['gi_delete'].value = gi;
  document.f.submit();
}

function handle_popup(w,h,name)
{
  var posx = screen.width - w;
  var posy = screen.height - h;

  var win = window.open('about:blank',
                        name,
                        'status=no,toolbar=no,scrollbars=yes,resizable=yes,width='+w+',height='+h+',screenX='+posx+',screenY='+posy+',left='+(posx-12)+',top='+(posy-60));

  win.focus();
  return win;
}

function show_alignment_frame()
{
  setVisibility(document.getElementById('graemlin_alignment'), true);
}

function getPageOffsetY(obj)
{
  var offset = 0;

  do
    offset += obj.offsetTop;
  while((obj = obj.offsetParent));

  return offset;
}

function getPageOffsetX(obj)
{
  var offset = 0;

  do
    offset += obj.offsetLeft;
  while((obj = obj.offsetParent));

  return offset;
}

function show_select_tooltip(obj, event)
{
  var tgt = event.target;

  if(tgt.parentNode != obj)
    return;

  var scrollOffsetY = (event.layerY - (event.pageY - getPageOffsetY(obj)));
  var tooltipY      = getPageOffsetY(tgt) - scrollOffsetY + 1;

  /* Fig bug where tooltip appears for one element above/below viewable area */
  if((tooltipY < getPageOffsetY(obj)) || (tooltipY >= (getPageOffsetY(obj) + obj.offsetHeight - 5)))
    return;

  var tt = document.getElementById('tooltip');
  if(!tt)
    return;

  tt.style.left = obj.offsetWidth + getPageOffsetX(obj);
  tt.style.top  = tooltipY;
  tt.innerHTML = tgt.text;

  setVisibility(tt, true);
}

function hide_select_tooltip(obj)
{
  var tt = document.getElementById('tooltip');
  if(!tt)
    return;

  setVisibility(tt, false);
}

function handle_graemlin()
{
  var check_db = false;
  var check_query = false;

  for(var i in document.f)
  {
    if(i.indexOf('databases[') != 0)
      continue;

    if(document.f[i].checked)
    {
      check_db = true;
      break;
    }
  }

  check_query = query_frame_form ? true : false;

  if(!check_db)
  {
    alert("You must select at least one database network!");
    return false;
  }

  if(!check_query)
  {
    alert("Please build a query first!");
    return false;
  }
}

function select_all(prefix, value)
{
  for(var i in document.f)
  {
    if(i.indexOf(prefix+'[') != 0)
      continue;

    document.f[i].checked = value;
  }
}

function handle_resubmit()
{
  document.f.submit();
}

function handle_searchmode()
{
  var r_simple = document.getElementById('searchmode_simple');
//MULTIPLE_SEARCH  var r_multiple = document.getElementById('searchmode_multiple');
  var r_neighborhood = document.getElementById('searchmode_neighborhood');

  var l_simple = document.getElementById('searchmode_simple_label');
//MULTIPLE_SEARCH  var l_multiple = document.getElementById('searchmode_multiple_label');
  var l_neighborhood = document.getElementById('searchmode_neighborhood_label');

  var d_simple = document.getElementById('searchmode_simple_div');
//MULTIPLE_SEARCH  var d_multiple = document.getElementById('searchmode_multiple_div');
  var d_neighborhood = document.getElementById('searchmode_neighborhood_div');

  if(!r_simple)
    return;

  var new_searchmode = 'simple';

  if(r_simple.checked)
    new_searchmode = 'simple';
//MULTIPLE_SEARCH  else if(r_multiple.checked)
//MULTIPLE_SEARCH    new_searchmode = 'multiple';
  else if(r_neighborhood.checked)
    new_searchmode = 'neighborhood';

  r_simple.checked       = new_searchmode == 'simple';
//MULTIPLE_SEARCH  r_multiple.checked     = new_searchmode == 'multiple';
  r_neighborhood.checked = new_searchmode == 'neighborhood';

  if(new_searchmode != 'simple')
  {
    l_simple.style.fontWeight = 'normal';
    setVisibility(d_simple, false);
  }
//MULTIPLE_SEARCH  if(new_searchmode != 'multiple')
//MULTIPLE_SEARCH  {
//MULTIPLE_SEARCH    l_multiple.style.fontWeight = 'normal';
//MULTIPLE_SEARCH    setVisibility(d_multiple, false);
//MULTIPLE_SEARCH  }
  if(new_searchmode != 'neighborhood')
  {
    l_neighborhood.style.fontWeight = 'normal';
    setVisibility(d_neighborhood, false);
  }

  if(new_searchmode == 'simple')
  {
    l_simple.style.fontWeight = 'bold';
    setVisibility(d_simple, true);
  }
//MULTIPLE_SEARCH  if(new_searchmode == 'multiple')
//MULTIPLE_SEARCH  {
//MULTIPLE_SEARCH    l_multiple.style.fontWeight = 'bold';
//MULTIPLE_SEARCH    setVisibility(d_multiple, true);
//MULTIPLE_SEARCH  }
  if(new_searchmode == 'neighborhood')
  {
    l_neighborhood.style.fontWeight = 'bold';
    setVisibility(d_neighborhood, true);
  }

  cur_searchmode = new_searchmode;

  update_addgenes_state();
  update_neighborhood_state();
}

function get_selected_genes()
{
  var gene_list = new Array();

  switch(cur_searchmode)
  {
    case 'simple':
    case 'neighborhood':
      {
        var listObj = document.getElementById(cur_searchmode == 'simple' ? 'search_simple_list' : 'search_neighborhood_list');
        for(var i=0 ; i < listObj.options.length ; ++i)
        {
          if(listObj.options[i].selected)
          {
            gene_list[listObj.options[i].value] = listObj.options[i].text;
          }
        }
        break;
      }

    case 'multiple':
      break;
  }

  return gene_list;
}

function get_selected_query_genes()
{
  var gene_list = new Array();

  if(query_frame_form)
  {
    for(var i=0 ; i < query_frame_form.length ; ++i)
    {
      var obj = query_frame_form[i];
      if(obj.name.indexOf('delete_') == 0 && obj.checked)
      {
        gene_list[gene_list.length] = obj.name.replace(/^delete_/, "");
      }
    }
  }

  return gene_list;
}

function handle_query_selection()
{
  update_clear_state();
}

function update_addgenes_state()
{
  var obj = document.getElementById('add_query');
  var gi_list = get_selected_genes();

  obj.disabled = gi_list.length == 0;
}

function update_clear_state()
{
  var clearObj    = document.getElementById('query_clear');
  var clearAllObj = document.getElementById('query_clear_all');

  var gi_delete = get_selected_query_genes();
  clearAllObj.disabled = !query_frame_form;
  clearObj.disabled = gi_delete.length == 0;
}

function update_query_frames()
{
  var frame = document.getElementById('queryFrame');
  var pictureFrame = document.getElementById('pictureFrame');

  if(!frame)
    return;

  frame.contentWindow.location.reload();
  pictureFrame.contentWindow.location.reload();
}

function handle_update_query_frames()
{
  if(xf_update_query.readyState != 4)
  {
    return;
  }

  var status = xf_update_query.status;
  if(status != 200)
  {
    write_debug("xf_update_query returned status=" + status + ", statusText="+xf_update_query.statusText);
    alert("An internal error occurred!");
    return;
  }

  update_query_frames();
}

/*******************************************************/
/*   XML Parsing                                       */
/*******************************************************/

function xml_get_text(el)
{
  if(el.nodeType == 3)
    return el.data;

  var text = "";
  for(var i = 0 ; i < el.childNodes.length ; ++i)
  {
    text += xml_get_text(el.childNodes[i]);
  }

  return text;
}

/*******************************************************/
/*   Fetching data                                     */
/*******************************************************/

var xf_search_simple;
var xf_search_neighborhood;
var xf_search_neighborhood_list;
var xf_update_query;

function newXMLHttpRequest()
{
  var req = false;
  // branch for native XMLHttpRequest object
  if(window.XMLHttpRequest) {
    try {
      req = new XMLHttpRequest();
    } catch(e) {
      req = false;
    }
    // branch for IE/Windows ActiveX version
  } else if(window.ActiveXObject) {
    try {
      req = new ActiveXObject("Msxml2.XMLHTTP");
    } catch(e) {
      try {
        req = new ActiveXObject("Microsoft.XMLHTTP");
      } catch(e) {
        req = false;
      }
    }
  }

  if(!req)
  {
    window.location = URL_BAD_BROWSER;
  }

  return req;
}

function init_xml_fetchers()
{
  xf_search_simple            = newXMLHttpRequest();
  xf_search_neighborhood      = newXMLHttpRequest();
  xf_search_neighborhood_list = newXMLHttpRequest();
  xf_update_query             = newXMLHttpRequest();
  xf_save_query               = newXMLHttpRequest();
}

function populate_list(xfObj, listObj)
{
  if(xfObj.readyState != 4)
  {
    return false;
  }

  write_debug("populate_list() invoked for listObj: " + listObj.id);

  listObj.options.length = 0;

  var status = xfObj.status;
  if(status != 200)
  {
    alert("An error occurred while performing this search!");
    return true;
  }

  var xml = xfObj.responseXML;
  var root = xml.firstChild;

  if(root.nodeName == "error")
  {
    alert(xml_get_text(root));
    return true;
  }
  else
  {
    for(var i=0 ; i < root.childNodes.length ; ++i)
    {
      var ch = root.childNodes[i];
      var gi = ch.getAttribute('gi');
      var descr = xml_get_text(ch);

      listObj.options[listObj.options.length] = new Option(descr, gi);
    }
  }

  return true;
}

function handle_submit(evt, fcn)
{
  if(window.event)
    evt = window.event;

  if(evt && evt.keyCode == 13)
  {
    fcn();
    return false;
  }

  return true;
}


/******************************************************/
/** Simple search                                    **/
/******************************************************/

function handle_search_simple()
{
  var query = trim(document.f['search_simple_query'].value);
  if(query == "")
  {
    alert("Please enter a query first!");
    return;
  }

  xf_search_simple.open("GET", URL_SEARCH_SIMPLE +
                               "?genome=" + escape(cur_species) +
                               "&query=" + escape(query),
                        true);
  xf_search_simple.onreadystatechange = pop_search_simple_list;
  xf_search_simple.send("");
}

function handle_search_simple_list()
{
  update_addgenes_state();
}

function pop_search_simple_list()
{
  var stateChanged = populate_list(xf_search_simple, document.getElementById('search_simple_list'));
  if(!stateChanged)
    return;

  update_addgenes_state();
}


/******************************************************/
/** Neighborhood search                              **/
/******************************************************/

function handle_search_neighborhood()
{
  var query = trim(document.f['search_neighborhood_query'].value);
  if(query == "")
  {
    alert("Please enter a query first!");
    return;
  }

  xf_search_neighborhood.open("GET", URL_SEARCH_SIMPLE +
                               "?genome=" + escape(cur_species) +
                               "&query=" + escape(query),
                        true);
  xf_search_neighborhood.onreadystatechange = pop_search_neighborhood_matches;
  xf_search_neighborhood.send("");
}

function pop_search_neighborhood_matches()
{
  var stateChanged = populate_list(xf_search_neighborhood, document.getElementById('search_neighborhood_matches'));
  if(!stateChanged)
    return;

  update_neighborhood_state();
  update_addgenes_state();
  write_debug("pop_search_neighborhood_list() calling handle_search_neighborhood_matches()");
  handle_search_neighborhood_matches();
}

function update_neighborhood_state()
{
  var listObj = document.getElementById('search_neighborhood_matches');
  var matchesObj = document.getElementById('searchmode_neighborhood_results_div');

  setVisibility(matchesObj, listObj.options.length ? true : false);
}

function handle_search_neighborhood_matches()
{
  var listObj = document.f['search_neighborhood_matches'];
  if(listObj.length == 0)
    return;

  var gi = listObj.options[listObj.selectedIndex].value;

  xf_search_neighborhood_list.open("GET", URL_SEARCH_NEIGHBORHOOD +
                                          "?genome=" + escape(cur_species) +
                                          "&gi=" + escape(gi),
                                   true);
  xf_search_neighborhood_list.onreadystatechange = pop_search_neighborhood_list;
  xf_search_neighborhood_list.send("");
}

function pop_search_neighborhood_list()
{
  populate_list(xf_search_neighborhood_list, document.getElementById('search_neighborhood_list'), true);
}

function handle_search_neighborhood_list()
{
  update_addgenes_state();
}


/******************************************************/
/** Query frame                                      **/
/******************************************************/

function update_query(qry)
{
  xf_update_query.open("POST", URL_UPDATE_QUERY, true);
  xf_update_query.onreadystatechange = handle_update_query_frames;
  xf_update_query.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
  xf_update_query.send(join("&", qry));
}

function handle_add_query()
{
  var qry = new Array();
  var gene_list = get_selected_genes();

  for(var gi in gene_list)
  {
    qry[qry.length] = "gi_list[" + escape(gi) + "]=" + escape(gene_list[gi]);
  }

  update_query(qry);
}

function handle_query_clear()
{
  var qry = new Array();
  var gene_list = get_selected_query_genes();

  for(var i=0 ; i < gene_list.length ; ++i)
  {
    qry[qry.length] = "gi_delete[]=" + escape(gene_list[i]);
  }

  update_query(qry);
}

function handle_query_clear_all()
{
  update_query(new Array('gi_delete=*'));
}


/******************************************************/
/** Save Query dialog                                **/
/******************************************************/

function show_save_query()
{
  var obj = document.getElementById('savequery');

  if(obj)
    setVisibility(obj, true);
}

function hide_save_query()
{
  var obj = document.getElementById('savequery');

  if(obj)
    setVisibility(obj, false);
}

function save_query(frm)
{
  var name          = frm['queryname'].value;
  var query_species = frm['query_species'].options[frm['query_species'].selectedIndex].value;

  var qry = "name=" + escape(name) +
            "&query_species=" + escape(query_species);

  for(var i in frm)
  {
    if(i.indexOf('databases[') != 0)
      continue;

    if(frm[i].checked)
      qry += ("&" + escape(i) + "=1");
  }

  xf_save_query.open("POST", URL_SAVE_QUERY, true);
  xf_save_query.onreadystatechange = handle_save_response;
  xf_save_query.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
  xf_save_query.send(qry);
}

function handle_save_response()
{
  if(xf_save_query.readyState != 4)
  {
    return;
  }

  var status = xf_save_query.status;
  if(status != 200)
  {
    write_debug("xf_save_query returned status=" + status + ", statusText="+xf_save_query.statusText);
    alert("An internal error occurred!");
    return;
  }

  var xml = xf_save_query.responseXML;
  var root = xml.firstChild;

  if(root.nodeName == "error")
  {
    alert(xml_get_text(root));
  }
  else
  {
    alert("Your query has been saved.");
    hide_save_query();
  }
}
