var granule = 10;
var res_lat = 0;
var res_lng = 0;
var max_col_cost = 2000000;
var min_col_cost = 0;

var max_vis_cost = 0;
var min_vis_cost = 0;
var avg_vis_cost = 0;
var median_cost = 0;
var numContours = 5;
var start_colour = Color.fromHexString( "#18cff2");
var mid_colour = Color.fromHexString( "ecff39" );
var end_colour = Color.fromHexString( "#f91604" );
var gridQueryServerRel = "/../cgi-bin/houseprices/housepricegrid.py/getGrid"
var dateQueryServerRel = "/../cgi-bin/houseprices/housepricegrid.py/getDates"
var URLDir = window.location.href.substring(0, location.href.lastIndexOf('\/'))
var gridQueryServer = URLDir + gridQueryServerRel;
var dateQueryServer = URLDir + dateQueryServerRel;
var google_map = null;
var curViewData = null;
var xindices = granule+1;
var yindices = granule+1;
var delayPeriod = 1000;
var delayTimer;

function load() {
    //setup ajax
    $("").ajaxError(onAjaxError);

  if (GBrowserIsCompatible()) {
    // Initialize
    if(document.implementation.hasFeature(
        "http://www.w3.org/TR/SVG11/feature#SVG","1.1")){
      _mSvgEnabled = true;
      _mSvgForced  = true;
    } 
    google_map = new GMap2(document.getElementById("map"));
    google_map.addControl(new GLargeMapControl());
    google_map.setCenter(new GLatLng(51.5, -0.12), 10);
    
    GEvent.addListener( google_map, "moveend", onMapMoveEnd );
    GEvent.addListener( google_map, "zoomend", onMapZoomEnd );
    
    
    getDateList();
  }
}

function onAjaxError(event, request, settings){
   alert("Error requesting page " + settings.url);
}

function getDateList(){
  $.getJSON( dateQueryServer, onGotDates );
}

function onGotDates( data )
{
  var datecombo = $("#date_select_id");
  var opts = "";
  
  var default_date = -1;
  
  for( var i in data )
  {
    var opt = "<option value='" + data[i][0] + "'>" + data[i][1] + "</option>";
    opts = opts + opt;
    
    if( default_date < data[i][0] )
    {
      default_date = data[i][0];
    }
  }
  
  datecombo.append( opts );
  datecombo[0].value = default_date; //most recent
  
  displayHouseInfo();
}

function loadDataGridToMap( datestr, beds ){
  var bounds = google_map.getBounds();
  var sw = bounds.getSouthWest();
  var ne = bounds.getNorthEast();
  
  var nw = new GLatLng( ne.lat(), sw.lng() );
  var se = new GLatLng( sw.lat(), ne.lng() );
  
  res_lat = (ne.lat() - sw.lat())/granule;
  res_lng = Math.abs(ne.lng() - sw.lng())/granule;
  
  loadDataGrid( nw, se, datestr, beds );
}

function loadDataGrid( topleftGPoint, botRightGPoint, datestr, beds ){
  
  if( beds == null ){
    beds = "*";
  }
  
  querymap = { "min_long": topleftGPoint.lng(), "long_dist" : botRightGPoint.lng() - topleftGPoint.lng(),
                 "max_lat" : topleftGPoint.lat(), "lat_dist": topleftGPoint.lat() - botRightGPoint.lat(),
                 "date_id" : datestr, "beds" : beds }

  var callback = onDataGrid;
  $.getJSON( gridQueryServer, querymap, callback );
}

function calcCosts()
{
  var sum = 0;
  var count = 0;
  var medianArray = new Array();
  min_vis_cost = 99999999999;
  max_vis_cost = 0;
  
  for( var xi = 0; xi < xindices; xi++ ){
    var lng = curViewData.lng( xi );
    
    for( var yi = 0; yi < yindices; yi++ ){
      var cost = curViewData.getValue( yi,xi );
      
      var lat = curViewData.lat( yi );
      
      if( cost != null )
      {
        count = count + 1;
        sum = sum + cost;
        medianArray.push( cost );
        if( cost > max_vis_cost ){
          max_vis_cost = cost;
        }
        
        if( cost < min_vis_cost ){
          min_vis_cost = cost;
        }
      }
            
    }
  
  }
  
  if( count != 0 )
  {
    avg_vis_cost = sum / count;
    medianArray.sort( function(a,b){return a - b;} );
    median_cost = medianArray[ parseInt( medianArray.length / 2 ) ];
  }
  else
  {
    avg_vis_cost = 0;
    median_cost = 0;
    max_vis_cost = 0
    min_vis_cost = 0;
  }
}

function onDataGrid( response ){
  var topleft = new GLatLng( response.top, response.left );
  curViewData = new squareData(  topleft, response.rowcount, response.colcount, response.xstep, response.ystep )
  
  curViewData.data = response.grid;
  
  calcCosts();
  plotHeatMap();
}

function log10( x )
{
     return (Math.log(x))/(Math.log(10));
}

function nicenum( x )
{
  var exp = Math.floor(log10(x));
  var f = x / Math.pow(10,exp);
  var nf;
  
  if( f < 0.5 )
  {
    nf = 0.25;
  }
  else if( f < 1 )
  {
    nf = 0.5;
  }
  else if( f < 1.5 )
  {
    nf = 1;
  }
  else if( f < 3 )
  {
    nf = 2;
  }
  else if( f < 7 )
  {
    nf = 5;
  }
  else
  {
    nf = 10;
  }
  
  return nf * Math.pow( 10, exp )
}

function getcostSteps()
{
  var bounds = [];
  var set = {};
  
  var nice_start = nicenum( min_vis_cost );
  var nice_step = nicenum( ( 2 * median_cost - min_vis_cost) / numContours );
  
  for( var i=0; i < numContours; i++ )
  {
    var nice = nice_start + i * nice_step;
    if( set[ nice ] == null )
    {
        bounds.push( nice );
        set[ nice ] = nice;
    }
  }
  
  return bounds;
}

function calcColourPt( startcol, endcol, percent )
{
  var colarray = [];
  
  var rstep = ( endcol.rgb.r - startcol.rgb.r );
  var gstep = ( endcol.rgb.g - startcol.rgb.g );
  var bstep = ( endcol.rgb.b - startcol.rgb.b );

  var r = startcol.rgb.r + rstep * percent;
  var b = startcol.rgb.b + bstep * percent;
  var g = startcol.rgb.g + gstep * percent;
  
  var c = Color.fromRGB( r, g, b );
  return c;
}

function calcColour( cost )
{
  //work out end col
  var startCol, endCol;
  var startCost, useCost;
  var midcost = ( max_col_cost + min_col_cost ) / 2;
  
  if( cost >= midcost )
  {
    startCol = mid_colour;
    endCol = end_colour;
    useCost = cost - midcost;
    startCost = midcost;
    endCost = max_col_cost;
  }
  else
  {
    startCol = start_colour;
    endCol = mid_colour;
    useCost = cost;
    startCost = min_col_cost;
    endCost = midcost;
  }
  
  return calcColourPt( startCol, endCol, ( cost -  startCost ) / ( endCost - startCost ) ); 
}

function calcColours( costs )
{
  var cols = [];
  
  var effcosts = [];
  effcosts.push( costs[0] / 2 );
  
  for( var j = 1; j < costs.length; j++ )
  {
    effcosts.push( (costs[j]-costs[i])/2 );
  }
  
  var enddiff =  (costs[costs.length-1] - costs[costs.length-2])/2.0;
  
  effcosts.push( ( costs[costs.length-1] + enddiff ) );
  
  for( var i in effcosts )
  {
    var cost = costs[i];
    cols.push( calcColour( cost ) );
  }
  
  return cols;
}

function getColour( cost, costs, colours )
{
  var rtnVal;
  
  //is min
  if( cost < costs[ 0 ] )
  {
    rtnVal = colours[0];
  }
  else if( cost >= costs[ costs.length - 1 ] )
  {
    rtnVal  = colours[ colours.length - 1 ];
  }
  else
  {
    for( var i = 0; i < costs.length - 1; i++ )
    {
      if( cost >= costs[i] && cost < costs[i+1] )
      {
        rtnVal = colours[ 1 + i ];
        break;
      }
    }
  }
  
  return rtnVal;
}

function plotHeatMap()
{  
  var costs = getcostSteps();
  var colours = calcColours( costs );
  
  drawKey( costs, colours );
  
  var lat_step = curViewData.lat_step / 2;
  var lng_step = curViewData.long_step / 2;
  
  for( var xi = 0; xi < xindices; xi++ ){
    var lng = curViewData.lng( xi );
    
    for( var yi = 0; yi < yindices; yi++ ){
      var cost = curViewData.getValue( yi,xi );
      if( cost != null )
      {
        var col = getColour( cost, costs, colours );
        
        var lat = curViewData.lat( yi );
        var top_left = new GLatLng( lat - lat_step, lng - lng_step );
        var top_right = new GLatLng( lat - lat_step, lng + lng_step );
        var bot_right = new GLatLng( lat + lat_step, lng + lng_step );
        var bot_left = new GLatLng( lat + lat_step, lng - lng_step );
        
        var pts = [ top_left, top_right, bot_right, bot_left ];
        
        var polygon = new GPolygon( pts, col, 0, 0, col, 0.4);
        google_map.addOverlay(polygon);
      }
    }
  }

}

function getDateStr()
{
  var datecombo = $("#date_select_id")[0];
  return datecombo.value;
}

function getBeds()
{
  return $("#bed_select_id")[0].value;
}

function createKey( txt, col )
{
  return "<table><tr><td>" + txt + "</td>" +
               "<td><div style='width:16px; height:16px; background-color:" + col + "'></div></td></tr></table>";
}

function drawKey( costVals, colList )
{
  if( costVals.length > 1 )
  {
    var totalkey = "";
    
    //do gt than max
    totalkey = createKey( "&gt; &pound;" + costVals[costVals.length - 1 ], colList[ colList.length - 1 ] );
    
    //do inbetweens
    for( var i = costVals.length -1; i > 0; i-- )
    {
      var col = colList[ i ];
      var txt = "&pound;" + costVals[ i - 1 ] + " - &pound;" + costVals[ i ];
      totalkey = totalkey + createKey( txt, col );
    }
    
    //do min
    totalkey = totalkey + createKey( "&lt; &pound;" + costVals[0], colList[0] )
    
    $("#keyspace").empty();
    $("#keyspace").append( totalkey );
  }
  else
  {
    $("#keyspace").empty();
    $("#keyspace").append( "No data..." );
  }
  
}

function displayHouseInfo()
{
  //clear overlays....
  google_map.clearOverlays();
  var beds = getBeds();
  loadDataGridToMap( getDateStr(), beds );
  
  var centre = google_map.getCenter();
  var bounds = google_map.getBounds();
  var botcentre = new GLatLng( bounds.getSouthWest().lat(), centre.lng() );
  var dist_m = centre.distanceFrom( botcentre );
  
  displayOodleAds( centre.lat(), centre.lng(), beds, "london", dist_m, "oodle_ads", google_map )
}

function startDataLoadTimer()
{
  if( delayTimer != null )
  {
    clearTimeout( delayTimer );
  }
  
  delayTimer = setTimeout( onDelayTimer, delayPeriod );
}

function onDelayTimer()
{
  clearTimeout( delayTimer );
  delayTimer = null;
  displayHouseInfo();
}

function onMapMoveEnd()
{
  startDataLoadTimer();
}

function onMapZoomEnd()
{
  startDataLoadTimer();
}

function onBedsChange()
{
  displayHouseInfo();
}
 
function onDateChange()
{
  displayHouseInfo();
}
