var displayType = null;  // grid or list

/**
 * One sustainable solution.
 *
 * TODO convert all to ValueRange.
 */
function Solution(iId, iType, sName, iCategoryId, sCategoryName, dCostMin, dCostMax, dCO2ReductionMin, dCO2ReductionMax, dSavingsMin, dSavingsMax, dPayOffYearsMin, dPayOffYearsMax, sDescription, oCO2Return, sImageURL, sUrl) {
  this.id = iId;
  this.type = iType;
  this.categoryId = iCategoryId;
  this.categoryName = sCategoryName;
  this.name = sName;
  this.costMin = dCostMin;
  this.costMax = dCostMax;
  this.co2ReductionMin = dCO2ReductionMin; 
  this.co2ReductionMax = dCO2ReductionMax;
  this.savingsMin = dSavingsMin;
  this.savingsMax = dSavingsMax;
  this.payOffYearsMin = dPayOffYearsMin;
  this.payOffYearsMax = dPayOffYearsMax;
  this.description = sDescription;
  this.co2Return = oCO2Return;
  this.image = sImageURL;
  this.url = sUrl;
  this.isOngoing = SolutionIsOngoing;
}

function SolutionIsOngoing() {
  return this.type == solutionTypeOngoing;
}

function ValueRange(dMin, dMax) {
  this.min = dMin;
  this.max = dMax;
}

function MemberImpact(sName, dCO2Savings, dCashSavings, iSolutionId) {
  this.name = sName;
  this.co2Savings = dCO2Savings;
  this.cashSavings = dCashSavings;
  this.solutionId = iSolutionId;
}

function ImpactCalculation(iSolutionId, sDescription, arrInputs, funcCalculator) {
  this.solutionId = iSolutionId;
  this.description = sDescription;
  this.inputs = arrInputs;
  this.calculator = funcCalculator;
}

/**
 * An element in the formula to calculate the impact for a solution.
 */
function FormulaInput(sName, sUnits, sDefault, bRequired) {
    this.name = sName;
    this.units = sUnits;
    this.defaultVal = sDefault;
    if (bRequired == null) {
        this.required = true;
    } else {
        this.required = bRequired;
    }
}

/**
 * A select element in the formula to calculate the impact for a solution.
 */
function FormulaInputSelect(sName, arrOptions) {
    this.name = sName;
    this.options = arrOptions;
}

/**
 * Write out the HTML of the list for the provided solutions into the div object.
 */
function renderSolutionsList(arrSolutions, objDiv) {
  var sHtml = "<div id='solutionsListWrapper'>";
  for (var i = 0; i < arrSolutions.length; i++) {
    var s = arrSolutions[i];
    sHtml += renderSolutionLarge(s);
  }
  sHtml += "</div>";
 
  objDiv.innerHTML = sHtml;
}

/**
 * Get the HTML of one solution in "large format".
 */
function renderSolutionLarge(s) {
  var sHtml = "<div class='solutionLarge'><h2><a href='" + s.url + "'>" + s.name + "</a></h2><div class='solutionWrapper'>";
  sHtml += "<div class=\"solutionLargeImage\"><img src=\"" + s.image + "\" height=\"150\" width=\"150\" border=\"0\"/></div>";
  sHtml += "<div class=\"solutionLargeDetails\">";
  sHtml += "<div>Known benefit and cost estimates</div><table class=\"solutionLargeTable\" cellpadding=\"0\" cellspacing=\"0\" border=\"0\">"
  sHtml += "<tr><th>Annual CO2 reduction</th><td>" + s.co2ReductionMin + " - " + s.co2ReductionMax + " kg</td></tr>";
  sHtml += "<tr><th>Annual cost savings</th><td>$" + s.savingsMin + " - $" + s.savingsMax + "</td></tr>";
  sHtml += "<tr><th>Initial Cost</th><td>$" + s.costMin + " - $" + s.costMax + "</td></tr>";
  sHtml += "<tr><th>Time to pay for itself</th><td>" + s.payOffYearsMin + " - " + s.payOffYearsMax + " years</td></tr>";
  sHtml += "<tr><th>CO2 reduced/year for each $ invested</th><td>" + s.co2Return.min + " - " + s.co2Return.max + " kg</td></tr>";
  sHtml += "</table>";
  sHtml += "<p class='smallfont solutionNote'>* The ranges are due to differences in methods of achieving this solution.</p>";
  sHtml += "</div>";
  sHtml += "<div class='solutionLinks'><a class='buttonImageMedium' href='" + s.url + "'><span>Full details</span></a> <a class='buttonImageMedium' href='" + websiteRoot + "/footprint/actions?solution_id=" + s.id + "'><span>Calculator</span></a> <a class='buttonImageMedium' href='" + websiteRoot + "/knowledge?category=" + s.categoryName + "'><span>Related articles</span></a> <a class='buttonImageMedium' href='" + websiteRoot + "/challenges/search?category=" + s.categoryName + "'><span>Challenges</span></a></div><br/><br/>";
  sHtml += "</div></div>";  
  return sHtml;
}

/**
 * Write out the HTML of the grid for the provided solutions into the div object.
 */
function renderSolutionsGrid(arrSolutions, objDiv) {
  objDiv.style.visibility = "hidden";
  var maxValue = getMaxValue(arrSolutions);
  var gridScaleFactor = maxValue / 740;
  var sHtml = "";

  var gridPos = findObjPosition(document.getElementById("solutionsArea"));

  // place grid markers
  var markerIntervals = [1000, 500, 100, 50, 10, 1];
  var markerInterval = 1000;
  for (var i = 0; i < markerIntervals.length; i++) {
    if (maxValue / markerIntervals[i] > 10) {
      markerInterval = markerIntervals[i];
      break;
    }
  }

  var markerIncrement = 2;
  if ((maxValue / markerInterval) < 10) {
    markerIncrement = 1;
  }

  for (var i = markerIncrement; i < (maxValue / markerInterval) + 1; i+=markerIncrement) {
    sHtml += "<div class='gridMarkerLabel' style='left: " + (((i*markerInterval)/gridScaleFactor)-20+gridPos.x) + "px; top: " + (gridPos.y-18) + "px'>" + (i*markerInterval) + "</div>";
    sHtml += "<div class='gridMarker' style='left: " + (((i*markerInterval)/gridScaleFactor)+gridPos.x) + "px; top: " + (gridPos.y-6) + "px'>|</div>";
  }

  // Create DIVs for each solution.
  for (var i = 0; i < arrSolutions.length; i++) {
    var s = arrSolutions[i];
    sHtml += "<div class='solutionSmallName' id='solutionSmallName" + i + "' onmouseover='gridSolutionMouseover(" + i + ", this)' onmouseout='gridSolutionMouseout(" + i + ", this)'><a href='javascript:void(0)' onclick='gridSolutionClick(" + i + ", this)'>" + s.name + "</a></div>";
    sHtml += "<div class='solutionSmallBar' id='solutionSmallBar" + i + "' onmouseover='gridSolutionMouseover(" + i + ", this)' onmouseout='gridSolutionMouseout(" + i + ", this)' onclick='gridSolutionClick(" + i + ", this)'>&nbsp;</div>";
    sHtml += "<div class='solutionSmallValue' id='solutionSmallValue" + i + "'>&nbsp;</div>";
  }

  objDiv.innerHTML = sHtml;

  var sortUnits = getSortUnits();

  // position the grid items
  for (var i = 0; i < arrSolutions.length; i++) {
    var s = arrSolutions[i];
    var value = getValueRange(s);
    if (value.min > 0) {
	$("#solutionSmallName" + i).css("left", (value.min / gridScaleFactor) + "px");
	$("#solutionSmallBar" + i).css("left", (value.min / gridScaleFactor) + "px");
	$("#solutionSmallBar" + i).css("width", ((value.max - value.min) / gridScaleFactor) + "px");
	$("#solutionSmallValue" + i).css("left", ((value.max / gridScaleFactor) + 10) + "px");
	$("#solutionSmallValue" + i).text(value.min + " - " + value.max + " (" + sortUnits + ")");
    }
  }
  
  objDiv.style.visibility = "visible";
}

/**
 * Get the maximum value of the currently selected sorting criteria for all solutions.
 */
function getMaxValue(arrSolutions) {
  var max = 0;
  for (var i = 0; i < arrSolutions.length; i++) {
    var criteria = getValueRange(arrSolutions[i]);
    if (criteria.max > max) {
      max = criteria.max;
    }
  }
  return max;
}

/**
 * Get the value of the selected sorting criteria for the provided solution
 */
function getValueRange(solution) {
  var type = getSortType();
  if (type == "cost") {
    return new ValueRange(solution.costMin, solution.costMax);
  } else if (type == "co2") {
    return new ValueRange(solution.co2ReductionMin, solution.co2ReductionMax);
  } else if (type == "savings") {
    return new ValueRange(solution.savingsMin, solution.savingsMax);
  } else if (type == "payoff") {
    return new ValueRange(solution.payOffYearsMin, solution.payOffYearsMax);
  } else if (type == "co2Return") {
    return solution.co2Return;
  }
}

function showGrid() {
  var solutionDiv = document.getElementById("solutionsArea");
  solutionDiv.className = "solutionsGrid";
  renderSolutionsGrid(solutions, solutionDiv);
  displayType = "grid";

  //var viewControls = document.getElementById("viewControls");
  //viewControls.innerHTML = "Change to <a href='javascript:void(0)' onclick='showList()'>list</a> view";
}

function showList() {
  var solutionDiv = document.getElementById("solutionsArea");
  solutionDiv.className = "solutionsList";
  renderSolutionsList(solutions, solutionDiv);
  displayType = "list";

  //var viewControls = document.getElementById("viewControls");
  //viewControls.innerHTML = "Change to <a href='javascript:void(0)' onclick='showGrid()'>grid</a> view";
}

function gridSolutionMouseover(intIndex, objElement) {
  $("#solutionSmallBar" + intIndex).css("border", "1px solid #4c4d3c");
  $("#solutionSmallBar" + intIndex).css("background-color", "#a7bf46");
  var barWidth = parseInt($("#solutionSmallBar" + intIndex).css("width"));
  var barLeft = parseInt($("#solutionSmallBar" + intIndex).css("left"));
  var barTop = parseInt($("#solutionSmallBar" + intIndex).css("top"));
  if (barWidth > 100) {
    var s = solutions[intIndex];
    var valRange = getValueRange(s);
    var text = valRange.min + " - " + valRange.max + " (" + getSortUnits() + ")";
    $("#solutionSmallBar" + intIndex).text(text);
  } else {
    var elementPos = findObjPosition(document.getElementById("solutionSmallBar" + intIndex));
    $("#solutionSmallValue" + intIndex).css("left", (elementPos.x + barWidth + 10) + "px");
    $("#solutionSmallValue" + intIndex).css("top", elementPos.y + "px");
    $("#solutionSmallValue" + intIndex).css("visibility", "visible");
  }
}

function gridSolutionMouseout(intIndex, objElement) {
  $("#solutionSmallBar" + intIndex).css("border", "1px solid #7e824d");
  $("#solutionSmallBar" + intIndex).css("background-color", "#9eb542");
  $("#solutionSmallBar" + intIndex).html("&nbsp;");
    $("#solutionSmallValue" + intIndex).css("visibility", "hidden");
}

function gridSolutionClick(intIndex, objElement) {
  var elementPos = findObjPosition(objElement);
  var objPopup = document.getElementById("gridSolutionPopup");

  var s = solutions[intIndex];

  var sHtml = "<div id='gridSolutionPopupClose'><a href='javascript:gridSolutionPopupClose()'>close</a></div><br/>";
  sHtml += renderSolutionLarge(s);

  //objPopup.innerHTML = sHtml;

  // Position the popup
  $("#gridSolutionPopup").css("top", (elementPos.y - 50) + "px");
  var gridPos = findObjPosition(document.getElementById("solutionsArea"));
  // Don't want to position too far to the right
  if (elementPos.x + 600 > gridPos.x + 800) {
    $("#gridSolutionPopup").css("left", (gridPos.x + 100) + "px");
  } else {
    $("#gridSolutionPopup").css("left", (elementPos.x + 25) + "px");
  }  
  
  $("#gridSolutionPopup").fadeIn(500).html(sHtml);
}

function gridSolutionPopupClose() {
  $("#gridSolutionPopup").fadeOut(250);
}

function getMousePosition(evt) {
  var posx = 0;
  var posy = 0;
  if (!evt) var evt = window.event;
  if (evt.pageX || evt.pageY) {
    posx = evt.pageX;
    posy = evt.pageY;
  }
  else if (evt.clientX || evt.clientY) {
    posx = evt.clientX + document.body.scrollLeft
      + document.documentElement.scrollLeft;
    posy = evt.clientY + document.body.scrollTop
      + document.documentElement.scrollTop;
  }
  return new Coordinates(posx, posy);
}

/**
 * Sort the global solutions array, depending on the value of the sort dropdown.
 */
function sortSolutions() {
  solutions = solutions.sort(solutionComparator);
  if (displayType == "grid") {
    showGrid();
  } else {
    showList();
  }

  var type = getSortType();
  var legend = document.getElementById("solutionsGridTopLegend");
  if (type == "cost") {
    legend.innerHTML = "Initial Cost ($)";
  } else if (type == "co2") {
    legend.innerHTML = "CO2 Savings / year (kg)";
  } else if (type == "savings") {
    legend.innerHTML = "Savings / year ($)";
  } else if (type == "payoff") {
    legend.innerHTML = "Time to pay off investment (years)";
  } else if (type == "co2Return") {
    legend.innerHTML = "CO2 Savings / year per dollar initially invested (kg)";
  }
}

/**
 * Sorting function for solutions, based off the currently selected sorting criteria.
 */
function solutionComparator(a, b) {
  var type = getSortType();
  if (type == "cost") {
    return compareValue(a.costMin, b.costMin);
  } else if (type == "co2") {
    return compareValue(a.co2ReductionMin, b.co2ReductionMin);
  } else if (type == "savings") {
    return compareValue(a.savingsMin, b.savingsMin);
  } else if (type == "payoff") {
    return compareValue(a.payOffYearsMin, b.payOffYearsMin);
  }
  return 0;
}

/**
 * Compare solutions a and b, returning -1, 0 or 1.
 */
function compareValue(a, b) {
  if (parseInt(a) > parseInt(b)) {
    return -1;
  } else if (parseInt(a) < parseInt(b)) {
    return 1;
  } else {
    return 0;
  }
}

/**
 * Get the currently selected sorting criteria.  Will be one of: co2, cost, savings, payoff.
 */
function getSortType() {
  var sorttype = document.getElementById("sorttype");
  var type = sorttype.options[sorttype.selectedIndex].value;
  return type;
}

/**
 * Get the units of the current sort.
 */
function getSortUnits() {
  var type = getSortType();
  if (type == "cost") {
    return "$";
  } else if (type == "co2") {
    return "kg";
  } else if (type == "savings") {
    return "$";
  } else if (type == "payoff") {
    return "years";
  } else if (type == "co2Return") {
    return "kg/$";
  } else {
    return "unknown";
  }
}


