var TimeslotRows = {
            early_am: [1, "8:30 am"],
            morning: [2, "10:30 am"],
            courier11: [3, "11:00 am"],
            noon: [4, "12:00 pm"],
            courier13: [5, "1:00 pm"],
            courier14: [6, "2:00 pm"],
            early_pm: [7, "3:00 pm"],
            courier16: [8, "4:00 pm"],
            evening: [9, "5:00 pm"],
            end_of_day: [10, "End of<br>Day"]
};
var Columns = 6;
var Times = ["early_am", "morning", "courier11", "noon", "courier13", "courier14", "early_pm", "courier16", "evening", "end_of_day"];
var Panels = [ $("#ratesByPriceDiv"), $("ratesByTransitDiv") ];
var Sliders = [];
var DayToDisplay = null;
var RatesData = null;

function emptyCells(n) {
  s = '';
  for (var i = 0; i < n; i++) {
    s += '<td></td>';
  }
  return s;
}

function inSpan(rate, content) {
  var classStr = "time" + TimeslotRows[rate.timeslot][0] + ' day' + rate.transit + ' price' + rate.rate.toFixed() + " courier" + rate.courier_code;
  return '<span class="' + classStr + '">' + content + "</span>";
}

function addParameter(params, name, value) {
  var term = name + "=" + encodeURI(value);
  return (params == null || params == "") ? term : params + "&" + term;
}

function transitionToUrl(rate) {
  params = addParameter("", "cell[courier]", rate.courier_name);
  params = addParameter(params, "cell[service]", rate.service);
  params = addParameter(params, "cell[price]", rate.rate);
  params = addParameter(params, "url", rate.url);
  return "/rates/transition?" + params;
}

function displayRate(r) {
  return inSpan(r,
  '<a class="result_data external-link" href="' + transitionToUrl(r) + '"><span class="price">$' + r.rate.toFixed(2) + '</span> '
      + '<img class="active-logo" src="/Content/images/logos/sm_' + r.courier_name.replace(/\s/g,"") + '.png" alt="' + r.courier_name + '" height="16">'
      + '<img class="inactive-logo" src="/Content/images/logos/sm_' + r.courier_name.replace(/\s/g, "") + 'Gray.png" alt="' + r.courier_name + '" height="16">'
      + '<br>' + r.service + '</a>');
}

function dayToColumn(day) {
  return (day >= Columns ? Columns-1 : day);
}

function fillInRatesByPrice(rates) {
    var mapping = [];
    for (var day = 0; day < Columns; ++day) mapping[day] = '';

    $.each(rates, function(index, r) {
        // column position of data
        var n = dayToColumn(r.transit);
        mapping[n] = appendRate(mapping[n], r);
    });
    var html = '<tr class="rate">';
    //html += emptyCells(n) + '<td>' + displayRate(r) + '</td>' + emptyCells((Columns - 1) - n)
    $.each(mapping, function(index, ratesForDay) {
        html += '<td>' + ratesForDay + '</td>';
    });
    html += '</tr>';

    //append the html to the table
    $('#ratesByPrice tbody').append(html);
}

function initializeRatesByTransitTimeMapping() {
  var mapping = {};
  $.each(Times, function(index, time) {
    var data = [];
    for (var day = 0; day < Columns; ++day) data[day] = '';
    mapping[time] = data;
  });
  return mapping;
}

function appendRate(content, r) {
  return content + (content == '' ? '' : '<br />') + displayRate(r);
}

function createRatesByTransitTimeMapping(rates) {
  var mapping = initializeRatesByTransitTimeMapping();
  $.each(rates, function(index, r) {
    //if (r.timeslot == null) r.timeslot = "end_of_day";
    var row = mapping[r.timeslot];
    var transit = r.transit;
    if (transit > 5) transit = 5;
    row[transit] = appendRate(row[transit], r)
  });
  return mapping
}

function displayRatesByTransitTime(mapping) {
    $.each(Times,
  function(index, row) {
      var slot = TimeslotRows[row];
      row = mapping[row];
      var html = '<tr class="rate"><th class="time_slot">' + slot[1] + '</th>';
      var rowHasData = false;
      $.each(row, function(idx, cell) {
          html += '<td class="col' + idx + '">' + cell + '</td>';
          if (cell != '') {
              rowHasData = true;
          }
      });
      html += '</tr>';
      if (rowHasData) {
          $('#ratesByTransit tbody').append(html);
      }
  });
}

function fillInRatesByTime(rates) {
  var mapping = createRatesByTransitTimeMapping(rates);
  displayRatesByTransitTime(mapping);
}

function createRatesTable(rates) {
  // used to set classes
  Rates = [];
  $.each(rates, function(index, r) {
    Rates[Rates.length] = Math.round(r.rate);
  });
}

/**
 * Filter rates to those for a given day column
 */
function ratesForColumn(rates, column) {
  results = [];
  $.each(rates, function(index, r){

    if (dayToColumn(r.transit) == column) {
      results[results.length] = r;
    }
  });
  return results;
}

/**
 * Sort function (to be passed to Array.sort) for sorting by timeslot
 */
function sortRatesByTimeSlot(a, b) {
  return TimeslotRows[a.timeslot][0] - TimeslotRows[b.timeslot][0];
}

/**
 * Sort function (to be passed to Array.sort) for sorting by price
 */
function sortRatesByPrice(a, b) {
  return a.rate.toFixed() - b.rate.toFixed();
}

function fillInRatesByTransitForDay(day) {
  $("#ratesByTransitForDay .dayText").hide();
  $("#ratesByTransitForDay .day" + day).show();
  $("#ratesByTransitForDay tbody").empty();

  var mapping = createRatesByTransitTimeMapping(RatesData);
  $.each(Times, function(index, row) {
      var slot = TimeslotRows[row];
      row = mapping[row];
      if (row[day] != "") {
          var html = '<tr class="rate"><th class="time_slot">' + slot[1] + '</th>';
          html += '<td class="col' + day + '">' + row[day] + '</td>';
          html += '</tr>';
          $("#ratesByTransitForDay tbody").append(html);
      }
  });
}

function fillInRatesByPriceForDay(day) {
  $("#ratesByPriceForDay .dayText").hide();
  $("#ratesByPriceForDay .day" + day).show();
  $('#ratesByPriceForDay tbody').empty();

  $.each(RatesData, function(index, r) {
    if (r.transit == day || (day == 5 && r.transit >= 5)) {
      var html = '<tr class="rate"><th>' + TimeslotRows[r.timeslot][1] + '</th><td>'  + displayRate(r) + '</td></tr>';
      $('#ratesByPriceForDay tbody').append(html);
    }
  });
}


function displayRates(rates) {
  RatesData = rates;
  fillInRatesByPrice(rates);
  fillInRatesByTime(rates);
  createRatesTable(rates);
}

function togglePanel(panelId) {
  $(".panel").hide(300, function() {
    $("#" + panelId).show(300);
  });
}

function updateDisplay() {
  var vtd = $('#view_type_display')[0];
  if ($('#sortBy').val() == "Price") {
    var panel = 'ratesByPrice';
    var sort = sortRatesByPrice;
    var fillFunction = fillInRatesByPriceForDay;
    vtd.innerHTML = 'Sorted by Price';
  } else {
    var panel = 'ratesByTransit';
    var sort = sortRatesByTimeSlot;
    var fillFunction = fillInRatesByTransitForDay;
    vtd.innerHTML = 'Sorted by Arrival Time';
  }

  if (DayToDisplay == null) {
    togglePanel(panel + "Div");
  } else {
    fillFunction(DayToDisplay);
    grayOutOfRangeRates();
    togglePanel(panel + "ForDayDiv");
  }

}

function displayRatesForDay(day) {
  DayToDisplay = day;
  updateDisplay();
}

function grayOutOfRangeRates() {
  $('span').removeClass("grayed");

  var deliveryDay = document.deliveryDay;
  if (deliveryDay != null) {
    $('span:not(.day' + deliveryDay + ')').addClass("grayed");
  }

  $('.courierCheckBox').each(function(i) {
    if (!this.checked) {
      $('span.courier' + this.value).addClass("grayed");
    }
  });

  var deliveryTime = parseInt($('.timeRadioButton:checked').val());
  if (deliveryTime != "all") {
    $('.timeRadioButton').each(function(i) {
      if (this.value != "all" && parseInt(this.value) > deliveryTime) {
        $('span.time' + this.value).addClass("grayed");
      }
    });
  }

  var maxPrice = Number(PriceSlider.value);
  if (maxPrice != null && maxPrice != MaxDisplayPrice) {
    $.each(Rates, function(index, price) {
      if (price > maxPrice) {
        $('span.price' + price).addClass("grayed");
      }
    });
  }
}

function updateRates() {
  $('#spinner').show();
  $('tr.rate').remove();
  $.getJSON('/rates', function(data) {
    displayRates(data);
    grayOutOfRangeRates();
    $('#spinner').hide();
  });
}

function getParams() {
  return $.map(arguments, function(v, i) { return v+'='+$('#'+v).val(); }).join("&");
}

function checkAllCarriers() {
  $('input.courierCheckBox').attr({ checked:true });
  $('input.courierCheckBox + label.prettyCheckbox').addClass('checked') // Pretty checkboxes
  grayOutOfRangeRates();
  return false;
}

function checkOnlyCarrier(carrier) {
  $('input.courierCheckBox').attr({ checked:false });
  $('input.courierCheckBox').siblings('label.prettyCheckbox').removeClass('checked') // Pretty checkboxes

  $('#checkBoxFor'+carrier).attr({ checked:true });
  $('label[for="checkBoxFor' + carrier + '"]').addClass('checked') // Pretty checkboxes

  grayOutOfRangeRates();
  return false;
}

function getCityForZip() {
  $("#" + this.id + "_city_state").load("/zip_code", {id: this.value});
}

function createPriceSlider(MaxDisplayPrice) {
  var allowedCodes = [
    8, 9,
    37, 38, 39, 40,
    96, 97, 98, 99, 100, 101, 102, 103, 104, 105,
    48, 49, 50, 51, 52, 53, 54, 55, 56, 57
  ];
  var PriceSlider = new Ext.Slider({
      renderTo: 'priceSlider', width: 140, value: MaxDisplayPrice, increment: 1, minValue: 0, maxValue: MaxDisplayPrice
  });
  var setSlider = function() {
    PriceSlider.setValue(Number($('#maxPriceInput').val()));
    grayOutOfRangeRates();
  };

  $('#maxPriceInput').keydown(
    function(event) {
      if (allowedCodes.indexOf(event.charCode || event.keyCode) != -1) {
        setTimeout(setSlider, 0);
      } else {
        if (event.stopPropagation) {
          event.stopPropagation();
        } else {
          event.cancelBubble = true;
        }
        if (event.preventDefault) {
          event.preventDefault();
        } else {
          event.returnValue = false;
        }
        event.stopped = true;
      }
    }
  );
  PriceSlider.on('change',
    function() {
      $('#maxPriceInput').val(this.value == MaxDisplayPrice ? '' : this.value.toFixed());
      grayOutOfRangeRates();
    }
  )
    return PriceSlider;
}

function updateSavedDate(formObj) {    
    //Find the date input #date in this form. (Be careful as there are many #dates on this page, so you have to find the specific date field in this form.
    var dateField = $("#date", formObj);
    var submitDate = new Date(dateField.val());   

    var currentDate = new Date();
    var sameDates = false;

    var newDateString = "";
    var newTimeString = "";
    
    //If the date is in past, make the date today.
    if (currentDate > submitDate) {
        //month is 0 based
        newDateString = currentDate.getMonth()+1 + "/" + currentDate.getDate() + "/" + currentDate.getFullYear();
        $("#date", formObj).val(newDateString);
        sameDates = true;
    }

    //The date is updated, so let's make sure the time is correct.
    if (sameDates) {
        var hours = $("#time", formObj).val();
        var originalDateTime = new Date(newDateString + " " + hours);
        if (originalDateTime < currentDate) {
        
            //Reset the time field to the nearest hour.
            var suffix = "AM"
            var hours = new Date().getHours() + 1

            if (hours == 24) {
                hours = 12
            } else if (hours >= 12) {
                suffix = "PM"
                hours = hours == 12 ? 12 : hours - 12
            }
            hours = hours + ":00 " + suffix

            newTimeString = hours; 
            $("#time", formObj).val(newTimeString);
        }
    }    
    
}