/*
 * Cost Calculator - jQuery plugin to run the Nasuni Filer cost over time.
 * Copyright (c) 2009 Nasuni Corp.
 */

$(function() {
      
    //--------------------------------------------
    // Constants
    //--------------------------------------------
    var ANIMATE_SPEED = 'slow';
    var FILER_MONTHLY_PRICE = 250.00;
    var YEARS_TO_CALC = 3;
    var NO_PROVIDER = '--Select Provider--';
    var PROVIDERS = {
      '--Select Provider--':   { shortname: "Provider",      price: 0.00 },
      'Amazon S3':             { shortname: "Amazon",        price: 0.15 },
      'AT&T Synaptic':         { shortname: "AT&T",          price: 0.25 },
      'Iron Mountain ASP':     { shortname: "Iron Mountain", price: 0.65 },
      'Nirvanix SDN':          { shortname: "Nirvanix",      price: 0.48 },
      'Rackspace Cloud Files': { shortname: "Rackspace",     price: 0.15 }
    };
    
    //--------------------------------------------
    // Define a few useful functions
    //--------------------------------------------
    function isEmpty(s) { return ((s == null) || (s.length == 0)) }
    function isDigit(c) { return ((c >= "0") && (c <= "9")) }
    function isInteger(s) {
      var i;
      if (isEmpty(s))
        if (isInteger.arguments.length == 1) return 0;
        else return (isInteger.arguments[1] == true);
      for (i = 0; i < s.length; i++) {
        var c = s.charAt(i);
        if (!isDigit(c)) return false;
      }
      return true;
    }
    
    //--------------------------------------------
    // Check the Values for any errors.
    //--------------------------------------------
    function checkErrors(data, growth, provider) {
      errors = false;
      // Check input 'Data'
      if ((!isInteger(data)) || (data <= 0)) {
        errors = true;
        if (data != '')
          setErrorMessage($('input[name="data"]'), "Value must be a whole number greater than 0.");
      }
      // Check input 'Growth'
      if ((!isInteger(growth)) || (growth < 0)) {
        errors = true;
        if (growth != '')
          setErrorMessage($('input[name="growth"]'), "Value must be a whole number 0 or greater.");
      }
      // Check input 'Provider'
      if (provider == NO_PROVIDER) {
        errors = true;
        setErrorMessage($('select[name="provider"]'), "Please select a provider.");
      }
      return errors;
    }
    
    // Add an error message to the specified input
    function setErrorMessage(input, message) {
        var container = input.parent().parent();
        container.addClass('error');
        container.append("<p class='error-msg'>"+ message +"</p>");
    }
    
    // Remove all Error Messages
    function removeErrorMessages() {
        $('#calculatorForm .error').removeClass('error');
        $('p.error-msg').remove();
    }
    
    //--------------------------------------------
    // Zero all Values
    //--------------------------------------------
    function zeroAllValues() {
      var numMonths = YEARS_TO_CALC * 12;
      var months = new Array(numMonths);
      for (var i=0; i<numMonths; i++)
        months[i] = {'estimateData': 0, 'nasuniCost': 0, 'storageCost': 0, 'totalCost': 0 }
      return months;
    }
    
    //--------------------------------------------
    // Calculate Cost by Month
    //--------------------------------------------
    function costByMonth(data, growth, provider) {
      var costGB = PROVIDERS[provider].price;
      var numMonths = YEARS_TO_CALC * 12;
      var monthlyGrowth = Math.pow(1+(growth/100), 1/12)-1;
      //console.log("UPDATE: data: "+data+" GB; growth: "+growth+ "%; costGB: '"+costGB+"'; monthlyGrowth: "+monthlyGrowth+"%");
      // Setup the First Month's Cost
      var months = new Array(numMonths);
      months[0] = {}
      months[0].estimateData = data;
      months[0].nasuniCost = FILER_MONTHLY_PRICE;
      months[0].storageCost = months[0].estimateData * costGB;
      months[0].totalCost = months[0].nasuniCost + months[0].storageCost;
      //console.log(">> 1: estimateData: "+months[0].estimateData+" GB; nasuniCost: $"+months[0].nasuniCost+"; storageCost: $"+months[0].storageCost+"; totalCost: $"+months[0].totalCost);
      // Calculate Other Month's Cost
      for (var i=1; i<numMonths; i++) {
        months[i] = {}
        months[i].estimateData = months[i-1].estimateData * (1+monthlyGrowth);
        months[i].nasuniCost = FILER_MONTHLY_PRICE;
        months[i].storageCost = months[i].estimateData * costGB;
        months[i].totalCost = months[i].nasuniCost + months[i].storageCost;
        //console.log(">> "+(i+1)+": estimateData: "+months[i].estimateData+" GB; nasuniCost: $"+months[i].nasuniCost+"; storageCost: $"+months[i].storageCost+"; totalCost: $"+months[i].totalCost);
      }
      return months;
    }
    
    //--------------------------------------------
    // Update Graph Table
    //--------------------------------------------
    function updateGraphTable(months, provider) {
      // Hide all the current Numbers
      $('#costTable td.value span').fadeOut(ANIMATE_SPEED, function() {
        var totalNasuniCost = 0;
        var totalStorageCost = 0;
        for (var year=1; year<=YEARS_TO_CALC; year++) {
          var start = (year-1)*12;
          var end = ((year-1)*12)+11;
          var nasuniCost = 0;
          var storageCost = 0;
          for (var i=start; i<=end; i++) {
            nasuniCost += months[i].nasuniCost;
            storageCost += months[i].storageCost;
          }
          totalNasuniCost += nasuniCost;
          totalStorageCost += storageCost;
          $('#costTable .nasuniCost .year'+year+' span').html('$'+insertCommas(Math.round(nasuniCost)));
          $('#costTable .storageCost .year'+year+' span').html('$'+insertCommas(Math.round(storageCost)));
          $('#costTable .total .year'+year+' span').html('$'+insertCommas(Math.round(nasuniCost+storageCost)));
        }
        $('#costTable .storageCost .rowLabel span').html(PROVIDERS[provider].shortname+" Cost");
        $('#costTable .nasuniCost .total span').html('$'+insertCommas(Math.round(totalNasuniCost)));
        $('#costTable .storageCost .total span').html('$'+insertCommas(Math.round(totalStorageCost)));
        $('#costTable .total .total span').html('$'+insertCommas(Math.round(totalNasuniCost+totalStorageCost)));
        $('#costTable td.value span').fadeIn(ANIMATE_SPEED);
      });
    }
    
    //--------------------------------------------
    // Update Graph
    //--------------------------------------------
    function updateGraph(months, provider) {
      // Build the Data arrays
      var nasuniData = [];
      var storageData = [];
      var numMonths = $('input[name="years"]').val() * 12;
      for (var i=0; i<numMonths; i++) {
        nasuniData.push([i+0.7, months[i].nasuniCost]);
        storageData.push([i+0.7, months[i].storageCost]);
      }
      
      // Update the Actual Graph
      var data = [
        { label: "Nasuni Cost", data: nasuniData, color: "#6BA5DF" },
        { label: PROVIDERS[provider].shortname+" Cost", data: storageData, color: "#E76F6B" }
      ];
      var options = {
        series: { stack: true, bars: { show: true, barWidth: 0.6 }},
        grid:   { backgroundColor: { colors: ["#fff", "#eee"] }},
        legend: { container: $('#costGraphLegend'), noColumns: 2 },
        xaxis:  { ticks: numMonths, tickDecimals: 0, min: 0.5, max: numMonths+0.5 },
        yaxis:  { min: 0, tickFormatter: function(num) { return "$"+Math.round(num); }}
      };
      $('#costGraph').animate({opacity: 0.01}, ANIMATE_SPEED, null, function() {
        $.plot($('#costGraph'), data, options);
        $('#costGraph').animate({opacity: 1}, ANIMATE_SPEED);
      });
    }
    
    //--------------------------------------------
    // Update The Graph and Chart Values
    //--------------------------------------------
    var lastValue = "UNDEFINED";
    function updateValues() {
      // Read Input Values
      var data = $('input[name="data"]').val();
      var growth = $('input[name="growth"]').val();
      var provider = $('select[name="provider"] option:selected').val();
      var months = zeroAllValues();
      //console.log("Provider: "+provider);
      // Check for Any Input Errors
      removeErrorMessages();
      if (checkErrors(data, growth, provider) == false)
        months = costByMonth(data, growth, provider);
      // Calculate the Monthly Costs
      if (lastValue != months[months.length-1].storageCost) {
        lastValue = months[months.length-1];
        updateGraph(months, provider);
        updateGraphTable(months, provider);
      }
    }
    
    //--------------------------------------------
    // Initialize the Cost Calculator Form
    //--------------------------------------------
    $('#javascript-disabled').remove();
    for (provider in PROVIDERS) {
      var price = PROVIDERS[provider].price;
      if (PROVIDERS[provider].shortname == "Provider") {
        $('select[name="provider"]').append("<option value='"+provider+"'>"+provider+"</option>");
      } else {
        $('select[name="provider"]').append("<option value='"+provider+"'>"+provider+" - $"+price+"/GB</option>");
      }
    }
    $('#calculatorForm').show();
    updateValues();
    
    // Attach the Input Change Triggers
    $('#calculatorForm').submit(function() { return false; });
    $('input[name="years"]').bind('change', updateValues);
    $('input[name="data"]').bind('change', updateValues);
    $('input[name="growth"]').bind('change', updateValues);
    $('select[name="provider"]').bind('change', updateValues);
    $('input[name="data"], input[name="growth"]').keyup(function(e) {
      if(e.keyCode == 13) { updateValues(); return false; }
    });
    
    // Attach the Year-Button Triggers
    $('div.year1').click(function() { $('input[name="years"]').val(1).triggerHandler('change'); });
    $('div.year2').click(function() { $('input[name="years"]').val(2).triggerHandler('change'); });
    $('div.year3').click(function() { $('input[name="years"]').val(3).triggerHandler('change'); });
    $('div.print').click(function() { window.print(); return false; });
    
});