// ==UserScript==
// @name         Google Auto Pager (Mnemonic Edition)
// @description  Auto-loads next page of Google search results.
// @include      http://www.google.*/search*
// @author       Protector one (and others)
// @namespace    http://twitter.com/Protector1
// @date         1 June 2010
// @version      1.9.1
// ==/UserScript==

(function(){
  var startNr, itemQuantity, storageContainer, query,
      tmpnodes, node, omitted, resultString,
      saveInx = 0,
      loadingElemID = 'nav',
      enabled = false,
      MEMLEN = 3000,
      base = "http://"+location.host+"/search";

  function endScroll(){
    if (remain() < 1100 && enabled){
      enabled = false;
      document.body.style.cursor = 'wait';
      doRequest();
      setTimeout(function(){
        document.body.style.cursor = 'auto';
      },300);
    }
  }
  
  function remain(){
    var scroll = document.documentElement.scrollTop;
    var total = document.documentElement.scrollHeight;
    return total - scroll;
  }
  
  function existNodeNN(){
    var bfl = document.getElementById('bfl');
    if (!bfl)
      return false;
    return startNr < parseInt(bfl.innerHTML.match(/\bswrnum=(\d+)/)[1])
  }
  
  function doRequest(){
    document.getElementById(loadingElemID).style.display = 'block';
    var url, xmlhttp = PRO_xmlhttpRequest();
    if (/start=/.test(query))
      url = base + query.replace(/start=\d+/,'start=' + startNr);
    else
      url = base + query + '&start=' + startNr;
    xmlhttp.open('GET', url, true); 
    xmlhttp.onreadystatechange = function(){
      if(xmlhttp.readyState == 4){
        document.getElementById(loadingElemID).style.display = 'none';
        var googleResult = document.createElement('div');
        googleResult.innerHTML = xmlhttp.responseText;
        googleResult.style.display = 'none';
        googleResult.id = 'googleResult';
        document.body.appendChild(googleResult);
        appendSearchResult();
      }
    }
    xmlhttp.send(null);
  }

  function appendSearchResult(){
    var i, list = getResultNodes();
    storageContainer.appendChild(list);
    for (i=0; i*MEMLEN <= list.outerHTML.length; ++i)
      PRO_setValue('GSAPitem'+(saveInx+i),list.outerHTML.substr(i*MEMLEN,MEMLEN));
    saveInx += i;
    if (omitted){
      var newb = document.createElement('p');
      newb.innerHTML = omitted;
      storageContainer.appendChild(newb);
    }
    startNr += itemQuantity;
    PRO_setValue('GSAPref',document.location.href);
    PRO_setValue('GSAPmaxItem',startNr);
    /*var res = resultString.innerHTML.match(/[\d|,|\.]+/g),
        resnum = parseInt(res[2].replace(',','').replace('.',''));
    if (list.length != itemQuantity){
      var nuw = startNr - itemQuantity + list.length;
      resultString.innerHTML = resultString.innerHTML.replace(res[2],nuw);
    }else{
      var nuw = Math.min(resnum,startNr);
    }
    resultString.innerHTML = resultString.innerHTML.replace(res[1],nuw);
    PRO_setValue('GSAPresults',resultString.innerHTML);*/
    if (existNodeNN())
      enabled = true;
    else
      insertEndText();
    document.body.removeChild(document.getElementById('googleResult'));
  }
  
  function getResultNodes(){
    var i, j, cname, ols,
        res = [],
        node = document.getElementById('googleResult'),
        pars = node.getElementsByTagName('p');
    for (i=0,j=pars.length; i<j; ++i)
      if (pars[i].id == 'ofr'){
        omitted = pars[i].innerHTML;
        PRO_setValue('GSAPomitted',omitted);
        break;
      }
    ols = node.getElementsByTagName('ol');
    for (i=0, j=ols.length; i<j; ++i)
      if (ols[i].parentNode.id == 'ires')
        return ols[i];
    return ols[0];
  }

  function insertEndText(){
    var elem = document.getElementById(loadingElemID)
    elem.innerHTML = "<br /><center>End of the search results</center>";
    elem.style.color = 'black';
    elem.style.fontWeight = 'bold';
    elem.style.display = 'block';
  }
  
  function insertLoadingText(){
    var wait = document.getElementById(loadingElemID);
    if(!wait)
      return;
    var par = wait.parentNode,
        nu = document.createElement('div');
    nu.id = loadingElemID;
    nu.innerHTML = '<div style="margin: 0 auto; width: 176px; height: 63px;"><p style="margin: 0; padding: 20px 0 0 15px; font-weight: bold; font-size: 130%; color: #222;">Loading</p></div>';
    par.replaceChild(nu,wait);
  }

  function makesSense(){
    var sense = document.getElementById('rhs');
    if (sense){
      sense.style.display = 'none';
    }
    sense = document.getElementById('tads');
    if (sense){
      sense.parentNode.removeChild(sense);
    }
  }

  function getStorageContainer(){
    storageContainer = document.getElementById('ires');
  }

  /*function getResultsCount(){
    var elms = document.getElementsByTagName('li');
    var count = 0;
    for(var i=0; i<elms.length; ++i){
      if(elms[i].className == 'g w0'){ ++count; }
    }
    return count;
  }*/

  function init(){
    query = location.search;
    var mini, tmp = query.match(/num=(\d+)/);
    //resultsCount = getResultsCount();
    itemQuantity = tmp ? parseInt(tmp[1]) : 10;
    mini = query.match(/start=(\d+)/);
    startNr = itemQuantity;
    if (mini)
      startNr += parseInt(mini[1]);
  }

  function dblClickEvents(){
    if (window.location.href.indexOf(base) > -1 && existNodeNN()){
      document.body.style.cursor = 'move';
      setTimeout(function(){
        document.body.style.cursor = 'auto';
      },200);
      enabled = !enabled;
      if (enabled)
        endScroll();
      else
        document.getElementById('nav').style.display = 'none';
    }
  }
  
  function checkHistory(){
    var ref = PRO_getValue('GSAPref');
    if (ref == location.href){
      var exist, content, i,
          maxi = parseInt(PRO_getValue('GSAPmaxItem')),
          addition = [];
      startNr = maxi;
      omitted = PRO_getValue('GSAPomitted','');
      //resultString.innerHTML = PRO_getValue('GSAPresults');
      exist = existNodeNN();
      if (!exist){
        insertLoadingText();
        insertEndText();
      }
      i = -1;
      while (content = PRO_getValue('GSAPitem'+(++i)))
        addition.push(content);
      saveInx = i;
      storageContainer.innerHTML += addition.join('');
      document.documentElement.scrollTop = parseInt(PRO_getValue('GSAPscroll',0));
      if (!exist && PRO_getValue('GSAPomitted','')){
        var newp = document.createElement('p');
        newp.innerHTML = omitted;
        storageContainer.appendChild(newp);
      }
    }else{
      var i = -1;
      while(PRO_getValue('GSAPitem'+(++i)))
        PRO_setValue('GSAPitem'+i,'')
      PRO_setValue('GSAPmaxItem','');
      PRO_setValue('GSAPomitted','');
      PRO_setValue('GSAPref','');
    }
  }
  
  function leave(){
    PRO_setValue('GSAPscroll',document.documentElement.scrollTop);
  }
  
  function getResultString(){
    resultString = document.getElementById('resultStats');
  }
  
  function main(){
    getResultString();
    getStorageContainer();
    makesSense();
    init();
    checkHistory();
    attachEvent('onbeforeunload', leave);
    if (existNodeNN()){
      insertLoadingText();
      enabled = true;
      attachEvent('onscroll', endScroll);
      document.body.attachEvent('ondblclick', dblClickEvents);
    }
  }
  
  main();

})();
