var request = null;
var lastUpdateRequest = null;
var curTimeCount = 0;
var allResults = new Array();

function showProgress() {
  document.getElementById("progressDiv").style.visibility = 'visible';
}

function hideProgress() {
  document.getElementById("progressDiv").style.visibility = 'hidden';
}

function getHttpRequest() {
    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;
         }
       }
    }
    return req;
}

function getSelectedIndicators() {
  var params = "";
  // find the selected points
  var count = 0;
  var inputs = document.getElementById('reportform').getElementsByTagName('input');
  for (var i = 0; i < inputs.length; i++) {
      if (inputs[i].type == "checkbox" && inputs[i].name == "indicator[]" && inputs[i].checked) {
        count++;
        params += "&indicator[]=" + inputs[i].value;
      }
  }
  if (count > 5) {
      alert("Select at most 5 indicators");
      return -1;
  }

  return params;
}

function getSelectedOptions() {
  var params = "";

  var inputs = document.getElementById('reportform').getElementsByTagName('input');
  for (var i = 0; i < inputs.length; i++) {
      if (inputs[i].className == "filteroption") {
          if (inputs[i].type == "text" && inputs[i].value != "") {
              params += "&" + inputs[i].name + "=" + inputs[i].value;
          } else if (inputs[i].type == "checkbox") {
              params += "&" + inputs[i].name + "=" + (inputs[i].checked ? "true" : "false");
          }
      }
  }

  var selects = document.getElementById('reportform').getElementsByTagName('select');
  for (var i = 0; i < selects.length; i++) {
      if (selects[i].className == "filteroption" && selects[i].options[selects[i].selectedIndex].value != "") {
          params += "&" + selects[i].name + "=" + selects[i].options[selects[i].selectedIndex].value;
      }
  }

  return params;
}

function clearSelectedPoints() {
  var inputs = document.getElementById('reportform').getElementsByTagName('input');
  for (var i = 0; i < inputs.length; i++) {
      if (inputs[i].type == "checkbox" && inputs[i].name == "indicator[]" && inputs[i].checked) {
        inputs[i].checked = false;
      }
  }
}

function runIndicators(strUser) {
  if (strUser == null) {
    strUser = "guest";
  }

  var ind = getSelectedIndicators();

  if (ind.length == 0) {
    alert("Choose at least one indicator");
    return;
  } else if (ind == -1) {
    alert("Error finding indicators");
    return;
  }

  var options = getSelectedOptions();

  request = getHttpRequest();
  request.onreadystatechange = filterCallback;
  try {
    request.open("GET", "runfilter.php?user=" + strUser + "&" + ind + "&" + options, true);
  } catch(e) {
    alert("Permission denied");
    return false;
  }
  request.send(null);
  curTimeCount = 0;
  showProgress();
}

function filterCallback() {
    // only if request shows "loaded"
    if (request != null && request.readyState == 4) {
        // only if "OK"
        if (request.status == 200) {
           var results = parseResults(request.responseText);
           populateResults(results, document.getElementById("responseDiv"));
           storeResults(results);
        } else {
            alert("There was a problem getting the filter.  Please try again shortly. (Error: " + request.statusText + ", code=" + request.status + ")");
        }
        hideProgress();
        request = null;
    }
}

// returns a RankingResults object
function parseResults(sResponse) {
  // we'll go line by line
  var aLines = sResponse.split("\n");

  // check for errors
  if (aLines.length < 3) {
    alert("We were unable to run the analysis right now.  Our systems may be undergoing maintenance.  We apologize for the inconvenience and ask to please try again later.");
    return;
  }

  // At least first 2 lines are meta data.  Rankings will begin with a $ at start of line.
  var date = aLines[0];
  var description = aLines[1];

  var results = new Array();

  for (var i = 2; i < aLines.length; i++) {
    var csv = aLines[i].split(",");
    if (csv[0] == "$" && csv.length > 5) {
      var ranking = new SymbolRanking(parseInt(csv[1])+1, csv[2], csv[3], csv[4], csv[5], csv[6], csv[7], csv[8], csv[9], csv[10], csv[11], csv[12], csv[13]);
      results[results.length] = ranking;
    }
  }
  var rankingResults = new RankingResults(description, date, results);

  if (aLines[2].charAt(0) == "%") {
    var csv = aLines[2].split(",");
    rankingResults.numRanked = parseInt(csv[1]);
    rankingResults.avgScore = parseInt(csv[2]);
  }

  return rankingResults;
}

function RankingResults(sDescription, sDate, aResults) {
  this.description = sDescription;
  this.date = sDate;
  this.results = aResults;
  this.numRanked = 0;
  this.avgScore = 0;
}

function SymbolRanking(iRank, sSymbol, dPrice, iScore, dOpen, dHigh, dLow, dPrevClose, iVolume, iAvgDailyVolume, dEPS, iRankChangeToday, iRankChangeYesterday) {
  this.rank = parseInt(iRank);
  this.symbol = sSymbol;
  this.price = parseFloat(dPrice);
  this.score = parseInt(iScore);
  this.open = parseFloat(dOpen);
  this.high = parseFloat(dHigh);
  this.low = parseFloat(dLow);
  this.prevClose = parseFloat(dPrevClose);
  this.volume = parseFloat(iVolume);
  this.avgDailyVolume = parseFloat(iAvgDailyVolume);
  this.eps = parseFloat(dEPS);
  this.rankChangeToday = iRankChangeToday;
  this.rankChangeYesterday = iRankChangeYesterday;
}

function populateResults(rankings, divElement) {
  var newHTML = "<h3>Scan name: <span class='resultskeys'>" + rankings.description + "</span></h3>";
  newHTML += "<h3>Used data from: <span class='resultskeys'>" + rankings.date + "</span></h3>";
  if (rankings.numRanked > 0) {
    newHTML += "<table class='resultsstats'><tr><td>Top 50 results</td><td>Symbols Scored (not excluded): " + rankings.numRanked + "</td><td>Average Score: " + rankings.avgScore + "</td><td><a href='help.php#rankingreports' target='_new'>What do these averages mean?</a></td></tr></table>";
  }
  newHTML += "<table id='stockranksresults' class='resultstable' border='0' cellspacing='0' cellpadding='0'><tr><th>Symbol</th><th>Score</th><th>Price</th><th>Low - High</th><th>Volume,<br/>Average</th><th>EPS</th><th>&nbsp;</th></tr>";
  for (var i = 0; i < rankings.results.length; i++) {
      var ranked = rankings.results[i];
      newHTML += "<tr>";
      newHTML += "<td class='symbol'><a href=\"" + symbolLinkTarget + ranked.symbol + "\" target=\"stockdata\">" + ranked.symbol  + "</td>";
      newHTML += "<td><span class='largerNumber'>" + ranked.score.toFixed(0) + "</span></td>";
      var changePercent = 100 * (ranked.price - ranked.prevClose) / ranked.prevClose;
      newHTML += "<td" + addColor(ranked.price, ranked.prevClose) + "><span class='largerNumber'>" + ranked.price.toFixed(2) + "</span><br/><span class='smallNumber'>" + (changePercent > 0 ? "+" : "") + changePercent.toFixed(2) + "%</span></td>";
      newHTML += "<td>" + ranked.low.toFixed(2) + " - " + ranked.high.toFixed(2) + "</td>";
      newHTML += "<td><span class='largeNumber'>" + formatVolume(ranked.volume) + "</span><br/><span class='smallNumber'>" + formatVolume(ranked.avgDailyVolume) + "</span></td>";
      newHTML += "<td nowrap " + addColor(ranked.eps) + ">" + ranked.eps.toFixed(3) + "</td>";
      newHTML += "<td class='actions'><a href=\"javascript:void(0)\" onclick=\"addToWatchlist('" + ranked.symbol + "', " + ranked.price + ")\"><img src=\"img/icon_add.gif\" title=\"Add to watch list\" border=\"0\"/></a> ";
      newHTML += "<a href=\"javascript:void(0);\" onclick=\"startShowScoreChart('" + ranked.symbol + "', this)\"><img src=\"img/icon_rankings.gif\" title=\"Show Chart\" border=\"0\"/></a></td>";
      newHTML += "</tr>";
  }
  if (rankings.results.length == 0) {
      newHTML += "<tr><td colspan='12' style='text-align: center'><p class='error'>No stocks returned. The options you selected may not match any stocks, or there may not be enough data today to filter yet.</p></td></tr>";
  }
  newHTML += "</table>";
  divElement.innerHTML = newHTML;  
}

function formatVolume(vol) {
    if (vol > 1000000000) {
        return (vol / 1000000000).toFixed(2) + "B";
    } else if (vol > 1000000) {
        return (vol / 1000000).toFixed(2) + "M";
    } else if (vol > 1000) {
        return (vol / 1000).toFixed(0) + "k";
    } else {
        return vol.toFixed(0);
    }
}

// store a new set of results in the local state
function storeResults(results) {
  allResults[allResults.length] = results;
  var select = document.getElementById("resultsselect");
  var name = results.description + " @ " + results.date;
  select.options[select.options.length] = new Option(name, select.options.length);
}

// show a stored set of results
function showResults() {
  var index = document.getElementById("resultsselect").selectedIndex - 1;
  if (index < 0) {
    return;
  }
  populateResults(allResults[index], document.getElementById("responseDiv"));
}

// otherValue is optional, will compare vs. that.
function addColor(value, otherValue) {
  if (otherValue != null) {
    if (value < otherValue) {
      return " class='results-neg'";
    } else if (value > otherValue) {
      return " class='results-pos'";
    }
  } else if (value < 0) {
    return " class='results-neg'";
  } else if (value > 0) {
    return " class='results-pos'";
  }
  return "";
}

function addSign(value) {
  if (value > 0) {
    return "+";
  } else if (value < 0) {
    return "-";
  }
  return "";
}

function stripQuotes(strText) {
  return replaceAll(strText, "\"", "");
}

function replaceAll( str, from, to ) {
    var idx = str.indexOf( from );

    while ( idx > -1 ) {
        str = str.replace( from, to );
        idx = str.indexOf( from );
    }

    return str;
}

function addFilter() {
  var objInput = document.getElementById("filterdescription");
  if (objInput == null) {
    alert("Error on page");
    return;
  }

  var params = getSelectedPoints();

  if (params == "" || params == -1) {
    // Alert already shown in getSelectedPoints()
    return;
  }

  var description = objInput.value;
  if (description == "") {
    alert("Please input a description");
    return;
  }

  window.location = "addfilter.php?addfilter=" + description + params;
}

function deleteFilter(intFilterIndex) {
  var filter = filters[intFilterIndex];
  window.location = "viewreport.php?deletefilter=" + filter.id;
}

/**
 * Add a symbol to the watchlist.  Asynchronous call.
 */
function addToWatchlist(strSymbol, dPrice) {
  if (user == "") {
    showStatusError("You are not logged in.");
    return;
  }

  if (strSymbol == "") {
    alert("Can't add a blank symbol");
    return;
  }
  if (dPrice == null) {
    alert("Can't add without a price");
    return;
  }

  showStatusWorking("Adding to watchlist...");
  request = getHttpRequest();
  request.onreadystatechange = addToWatchlistCallback;
  try {
    request.open("GET", "addtowatchlist.php?symbol=" + strSymbol + "&price=" + dPrice, true);
  } catch(e) {
    return false;
  }
  request.send(null);
}

function addToWatchlistCallback() {
  // only if request shows "loaded"
  if (request.readyState == 4) {
      // only if "OK"
      if (request.status == 200) {
        showStatusComplete("Symbol added to watchlist.");
      } else {
        showStatusError("Error adding symbol to watchlist.");
      }
  }    
}

var preloadChartImage = null;

function startShowScoreChart(strSymbol, objElement) {
  var objInfo = document.getElementById("scoreChart");
  objInfo.style.visibility = "hidden";
  var arrXY = findObjPosition(objElement);
  objInfo.style.top = arrXY[1] - 100;

  var imageURL = "stockrankschart.php?symbol=" + strSymbol + "&price=true&width=325";
  preloadChartImage = new Image();
  preloadChartImage.src = imageURL;

  showStatusWorking("Loading chart...");
  window.setTimeout("showScoreChart()", 1000); 
}

function showScoreChart() {
  var objInfo = document.getElementById("scoreChart");

  var html = "<div id='scoreChartClose'><a href='javascript:void(0)' onclick='hideScoreChart()'>close</a></div>";
  html += "<img id='scoreChartImage' src='" + preloadChartImage.src + "' width='325' height='300'/>";
  html += "<p>This chart shows the combined scores of the two top-performing overbought and oversold filters within the public back-test results.</p>";
  objInfo.innerHTML = html;
  objInfo.style.visibility = "visible";
  hideStatus();
}

function hideScoreChart() {
  var objInfo = document.getElementById("scoreChart");
  objInfo.style.visibility = "hidden";
}

function showLatestUpdate() {
  if (lastUpdateRequest != null) {
    return;
  }
  lastUpdateRequest = getHttpRequest();
  lastUpdateRequest.onreadystatechange = lastUpdateCallback;
  try {
    lastUpdateRequest.open("GET", "latestupdate.php", true);
  } catch(e) {
    alert("Permission denied");
    return false;
  }
  lastUpdateRequest.send(null);
}

function lastUpdateCallback() {
  // only if request shows "loaded"
  if (lastUpdateRequest != null && lastUpdateRequest.readyState == 4) {
    // only if "OK"
    if (lastUpdateRequest.status == 200) {
      var element = document.getElementById("lastUpdateDiv");
      element.innerHTML = lastUpdateRequest.responseText;
    }
    lastUpdateRequest = null;
    window.setTimeout("showLatestUpdate()", 60*1000); 
  }
}
