//based on code at http://code.google.com/apis/base/samples/javascript/tutorial.html

//TODO
//  use OO to avoid global vars (fix 'keywords_input' var)
//  internationalise (fix color/colour)

var map = null;
var geocoder = null;
var markers = [];
var markerHtmls = [];
var bounds = null;
//var imgPrefix = 'http://base.googlehosted.com/base_media?size=2&q=';
var imgPrefix = 'media.php?size=2&q=';
var baseURL = 'http://www.google.com/base/feeds/snippets/-/vehicles';
var max_values = 30;
var max_results = 250;

/**
 * This function is called when the page loads.  It renders the map,
 * instantiates the geocoder, and calls getMakeOptions() to get the list 
 * of different makes of vehicles.
 */
function onLoad() {
  //resetForm();
  Gload();
  getMakeOptions();
}
function Gload() {
  if (GBrowserIsCompatible()) {
    map = new GMap2(document.getElementById('map_div'));
    map.addControl(new GSmallMapControl());
    map.addControl(new GMapTypeControl());
    map.setCenter(new GLatLng(53, -2.2), 6);
    
    GEvent.addListener(map, 'click', function(marker, point) {
      for (var i = 0; i < markers.length; i++) {
        if (marker == markers[i]) {
          marker.openInfoWindowHtml(markerHtmls[i]);
        }
      }
    });

    geocoder = new GClientGeocoder();
    bounds = new GLatLngBounds();
    centerAndZoomMap();
  }
}
function autoLoad() {
  if (readCookie('autoload')) {
    getSnippets();
  }
}
function getModelsOnChange() {
  eraseCookie('autoload');
  getModels();
}

/*********************
 *  Google Maps API  *
 *********************/
// This function centers the map and sets the zoom level based the lat/long of the markers.
function centerAndZoomMap() {
  map.setZoom(map.getBoundsZoomLevel(bounds));
  map.setCenter(bounds.getCenter());
}

/**
 * This function draws a marker on the map at the given address. 
 */
function showAddress(address, title, alturl, imgLinks) {
  geocoder.getLatLng(
    address,
    function(point) {
      if (point) {
        var marker = new GMarker(point);
        bounds.extend(point);
        centerAndZoomMap();
        //populates array
        markers.push(marker);
        map.addOverlay(marker);
        var html = '<a href="' + alturl + '">' + title + '</a>';
        
        if (imgLinks) {
          html += '<br/>';
          var imgIndex = 0;
          while (imgIndex < 3) {
            if (imgLinks[imgIndex]) {
              html += '<a href="' + alturl + '"><img class="vehicleimg" src="' + imgPrefix + imgLinks[imgIndex].$t + '"/></a>';
            }
            imgIndex++;
          }
        }
        //populates array
        markerHtmls.push(html);
      }
    });
}

// This function displays the appropriate HTML in the InfoWindow of a marker.
function openInfoWindow(markerIndex) {
  markers[markerIndex].openInfoWindowHtml(markerHtmls[markerIndex]);
}

// This function is called before each query to remove old markers from the map.
function clearMarkers() {
  map.clearOverlays();
  bounds = new GLatLngBounds();
  markers = [];
  markerHtmls = [];
}

/*****************
 * JSON Parsing  *
 *****************/
 
 /**
 * This function parses the JSON results to create a dropdown 
 * menu of all the vehicle make options.
 */
function showMakeOptions(json) {
  // transform the JSON results into a drop down menu
  var select = document.getElementById('make_options');
 
  select.disabled = false; // enable the dropdown
  select.onchange = getModelsOnChange;
  select.options[select.selectedIndex].text = 'Any Make';

  for (var i = 0; i < json.feed.entry.length; ++i) {
    var entry = json.feed.entry[i];
    
    // find the make entry
    if (entry.title.$t == 'make(text)') {
      makeList = entry.gm$attribute.gm$value;
      //makeList.sort;
      makeList.sort(function(a,b) { return ( ( a.$t == b.$t ) ? 0 : ( ( a.$t > b.$t ) ? 1 : -1 ) ) } );
      //add important makes
      for (var j = 0; j < _makes.length; ++j) {
        makeList.splice(0,0,{"count":"1","$t":_makes[j]});
      }
      for (var j = 0; j < makeList.length; ++j) {
        var option = document.createElement('option');
        make = makeList[j].$t;
        make=(make + '').replace(/^(.)|\s(.)/g, function ($1) { return $1.toUpperCase(); });
        option.appendChild(document.createTextNode(make));
        select.appendChild(option);
        if (readCookie('make') == make) {
          select.options[select.length-1].selected=true;
          select.selectedIndex = select.length-1;
          getModels();
        }
      }
      break;
    }
  }
  document.getElementById('make_div').appendChild(select);
}

/**
 * This function parses the JSON results to create a dropdown 
 * menu of all the models for a particular make.
 */
function showModelOptions(json) {
  //Create or reset the options in the drop down box
  var select = document.getElementById('model_options');
  select.disabled = false;
  //select.options[0].disabled = true;
  // Use 1 instead of 0 so we don't delete the first option
  while (select.length > 1) {
     select.remove(1);
  }
  
  if (!json.feed.entry) {
    select.disabled = true;
    return false;
  }
  
  // Find the 'model' entry
  for (var i = 0; i < json.feed.entry.length; ++i) {
    var entry = json.feed.entry[i];

    if (entry.title.$t == "model(text)") {

      // Create an <option> element for each model
      makeList = entry.gm$attribute.gm$value;
      //makeList.sort(function(a,b) { return ( ( a.$t == b.$t ) ? 0 : ( ( a.$t > b.$t ) ? 1 : -1 ) ) } );
      for (var j = 0; j < makeList.length; ++j) {
        var option = document.createElement('option');
        make = makeList[j].$t;
        make=(make + '').replace(/^(.)|\s(.)/g, function ($1) { return $1.toUpperCase(); });
        option.appendChild(document.createTextNode(make));
        if (readCookie('model') == make) { option.selected=true; }
        select.appendChild(option);
      }
            
      // Don't process any more entries 
      break;
    }
  }
  //Done loading
  autoLoad();
}


/**
 * This function parses the JSON results to display vehicle information and 
 * put a marker on the map for each car.
 */
function showSnippets(json) {
  // get rid of the old search results
  clearOldSnippets();
  clearMarkers();
  
  // hide first, display later
  document.getElementById('vehicleresults').style.display='none';

  // check for results  
  if (json.feed.openSearch$totalResults.$t < 1) {
    alert('Sorry, ' + json.feed.openSearch$totalResults.$t + ' results found.');
    return false;
  }

  // display snippets area
  document.getElementById('vehicleresults').style.display='block';
  
  //load the map
  Gload();

  // create a table to  list the results
  var snippet_list = document.createElement('table');
  snippet_list.style.margin = 0;
  document.getElementById('snippets_div').appendChild(snippet_list);

  // use the JSON results to populate the table with images and vehicle information
  for (var i = 0; i < json.feed.entry.length; ++i) {
    var entry = json.feed.entry[i];

    // Create the table data elements for displaying the information
    var firstRow = snippet_list.insertRow(snippet_list.rows.length);
    firstRow.style.border = '1px';

    var imgCell = firstRow.insertCell(0);
    imgCell.setAttribute('class', 'snippet-data');
    imgCell.setAttribute('className', 'snippet-data');
    imgCell.rowSpan = 3;
    
    var titleCell = firstRow.insertCell(1);
    titleCell.colSpan = 2;
    titleCell.setAttribute('class', 'snippet-title');
    titleCell.setAttribute('className', 'snippet-title');
  
    var secondRow = snippet_list.insertRow(snippet_list.rows.length);
    var priceCell = secondRow.insertCell(0);
    priceCell.setAttribute('class', 'snippet-data');
    priceCell.setAttribute('className', 'snippet-data');
    
    var locationCell = secondRow.insertCell(1);
    locationCell.setAttribute('class', 'snippet-data');
    locationCell.setAttribute('className', 'snippet-data');
  
    var thirdRow = snippet_list.insertRow(snippet_list.rows.length);
  
    var yearCell = thirdRow.insertCell(0);
    yearCell.setAttribute('class', 'snippet-data');
    yearCell.setAttribute('className', 'snippet-data');
    
    var colourCell = thirdRow.insertCell(1);
    colourCell.setAttribute('class', 'snippet-data');
    colourCell.setAttribute('className', 'snippet-data');
  
    // get an image of the car
    if (entry.g$image_link) {
      // sort so images are always in the same order
      entry.g$image_link.sort(function(a,b) { return ( ( a.$t == b.$t ) ? 0 : ( ( a.$t > b.$t ) ? 1 : -1 ) ) } );
      var img = document.createElement('img');
      img.src = imgPrefix + entry.g$image_link[0].$t;
      imgCell.appendChild(img);
    }

    // get the price and mileage of the car
    var price;
    if (entry.g$price) {
      var splitIdx = entry.g$price[0].$t.indexOf('.');
      price = entry.g$price[0].$t.slice(0, splitIdx);
    } else {
      price = 'Not listed';
    }
    var mileage;
    if (entry.g$mileage) { 
      mileage = entry.g$mileage[0].$t;
    } else {
      mileage = '?';
    }
    priceCell.innerHTML = _currsym + price + ' ' + mileage + 'm';

    // get the location of the car
    var location;
    if (entry.g$location) {
      location = entry.g$location[0].$t;
    } else {
      location = 'Location: Unknown';
    }
    locationCell.innerHTML = location;

    // get the year the car was made
    var year;
    if (entry.g$year) {
      year = 'Year: ' + entry.g$year[0].$t;
    } else {
      year = 'Year: Unknown';
    }
    yearCell.innerHTML = year;
    
    // get the colour of the car
    var colour;
    if (entry.g$colour) {
      colour = 'Colour: ' + entry.g$colour[0].$t;
    } else {
      colour = 'Colour: Unknown';
    }
    colourCell.innerHTML = colour; 

    // add a link to the car seller's page to the snippet title
    var linkCell = document.createElement('td');
    firstRow.appendChild(linkCell);
    var alturl;
    for (var k = 0; k < entry.link.length; ++k) {
      if (entry.link[k].rel == 'alternate') {
        alturl = entry.link[k].href; 
        break;
      }
    }
    titleCell.innerHTML = '<a href="' + alturl + '">' + entry.title.$t + '</a>' +
    ' <a onclick="openInfoWindow(' + i + ')">(Show on map)</a>';
    
    // get the location and put a marker on the map
    if (entry.g$location) {
      var loc = entry.g$location[0];
      var txt = null;
      if (loc) {
        txt = document.createTextNode(entry.title.$t + ' - ' + loc.$t);
        showAddress(loc.$t, entry.title.$t, alturl, entry.g$image_link);
      } else {
        txt = document.createTextNode(entry.title.$t);
      }
    }
  }
}

/*********************
 *  Google Base API  *
 *********************/

/**
 * This function adds a JSON script element which queries Google Base and calls the 
 * call-back function.
 */

function getMakeOptions() {
  // Add a script element with the src set to the Google Base query for vehicle
  // makes. The JSON output is specified by including the alt=json-in-script
  // argument. The callback function is also specified as a URI argument.
  // This is equivalent to adding a script tag that looks like this:
  // <script type="text/javascript" src="http://www.google/com/base/feed/attributes/.." /> 

  var attributesElement = document.createElement('script');
  attributesElement.setAttribute('id', 'attributes');
  attributesElement.setAttribute('src', 
      'http://www.google.com/base/feeds/attributes/-/vehicles?max-values=' + max_values +
      '&bq=[target country:' + _country + ']' +  
      '&alt=json-in-script&callback=showMakeOptions');
  attributesElement.setAttribute('type', 'text/javascript');
  document.documentElement.firstChild.appendChild(attributesElement);
}

/**
 * This function queries the attributes feed for a JSON result and 
 * sets a callback to the showModelOptions() function.
 */
function getModels() {
  // Add a script element with the src set to the Google Base query for vehicle  
  // models.  The JSON output is specified by including the alt=json-in-script 
  // argument. The callback function is also specified as a URI argument.
  // This is equivalent to adding a script tag that looks like this:
  // <script type="text/javascript" src="http://www.google/com/base/feed/attributes/.." /> 

  makeOptions = document.getElementById('make_options');
  make = makeOptions.options[makeOptions.selectedIndex].text;

  var attributesElement = document.createElement('script');
  attributesElement.setAttribute('id', 'attributes');
  url = ['http://www.google.com/base/feeds/attributes/-/vehicles?max-values=', max_values,
       '&bq=[make:', make, '][target country:', _country, ']&alt=json-in-script&callback=showModelOptions'].join('');
  attributesElement.setAttribute('src', url);
  attributesElement.setAttribute('type', 'text/javascript');

  document.documentElement.firstChild.appendChild(attributesElement);
}


/**
 * This function queries the snippets feed for a JSON result and 
 * sets a callback to the showSnippets() function.
 */
function getSnippets(orderby) {
  // Add a script element with the Google Base query to get snippets for 
  // vehicles of a particular make and model. 
  // The JSON output is specified by including the alt=json-in-script argument.
  // The callback function is also specified as a URI argument.
  // This is equivalent to adding a script tag that looks like this:
  // <script type="text/javascript" src="http://www.google/com/base/feed/snippets/.." /> 

  // get search criteria for query
  location_input = document.getElementById('location_input').value;
  makeOptions = document.getElementById('make_options');
  make = makeOptions.options[makeOptions.selectedIndex].text; //use text for ie quirks
  modelOptions = document.getElementById('model_options');
  model = modelOptions.options[modelOptions.selectedIndex].text; //use text for ie quirks
  min_price = document.getElementById('min_price').value;
  max_price = document.getElementById('max_price').value;
  keywords_input = document.getElementById('keywords_input').value;
  loc_sort_input = document.getElementById('location_sort_input').value;

  // build the query
  var query = 'bq=';
  
  query = query + '[target country:' + _country + ']';
  query = query + '[link:' + _domain + ']';

  if (location_input != '') {
    query = query + '[location:@"' + location_input + '" %2B' + _radius + 'mi]';
  }
  if (make != 'Any Make') {
    query = query + '[make:' + make + ']';
  }
  if (model != 'Any Model') {
    query = query + '[model:"' + model + '"]';
  }
  if (min_price != '') {
    query = query + '[price:' + min_price + '..' + max_price + ']';
  }
  if (keywords_input != '') {
    query = query + '&q='+keywords_input;
  }
  if (orderby == 'price') {
    query = query + '&orderby=price(float%20' + _curr + ')&sortorder=ascending';
  }
  if (orderby == 'year') {
    query = query + '&orderby=year(int)&sortorder=descending';
  }
  if (orderby == 'mileage') {
    query = query + '&orderby=mileage(int)&sortorder=ascending';
  }
  if (orderby == 'location') {
    query = query + '&orderby=[x=location(location):neg(min(dist(x,@"' + loc_sort_input + '")))]';
  }
  
  query = query + '&max-results=' + max_results;
    
  // build the Base API URL
  var url = 'http://www.google.com/base/feeds/snippets/-/vehicles?' + query + 
      '&alt=json-in-script&callback=showSnippets';
  //alert(url);//debug

  // Create a script element that references the snippets feed query
  // Example URL: 
  // http://www.google.com/base/feeds/snippets/-/vehicles/?bq=[make:ford][model:taurus]&alt=json-in-script&callback=showSnippets
  var attributesElement = document.createElement('script');
  attributesElement.setAttribute('id', 'attributes');
  attributesElement.setAttribute('src', url);
  attributesElement.setAttribute('type', 'text/javascript');
  document.documentElement.firstChild.appendChild(attributesElement);

  //set cookies
  createCookie('make',make,1);
  createCookie('model',model,1);
  createCookie('autoload',1,1);
}


/******************
 *  Housekeeping  *
 ******************/
function clearOldSnippets() {
  var div = document.getElementById('snippets_div');
  if (div && div.firstChild) {
    div.removeChild(div.firstChild);
  }
}

function resetForm() {
  document.getElementById('location_input').value = '';
  document.getElementById('min_price').value = '';
  document.getElementById('max_price').value = '';
  document.getElementById('keywords_input').value = '';
  eraseCookie('make');
  eraseCookie('model');
}

/* cookie monster says: Grrr! */
function createCookie(name,value,days) {
	if (days) {
		var date = new Date();
		date.setTime(date.getTime()+(days*24*60*60*1000));
		var expires = '; expires='+date.toGMTString();
	}
	else var expires = '';
	document.cookie = name+'='+value+expires+'; path=/';
}

function readCookie(name) {
	var nameEQ = name + '=';
	var ca = document.cookie.split(';');
	for(var i=0;i < ca.length;i++) {
		var c = ca[i];
		while (c.charAt(0)==' ') c = c.substring(1,c.length);
		if (c.indexOf(nameEQ) == 0) return c.substring(nameEQ.length,c.length);
	}
	return null;
}

function eraseCookie(name) {
	createCookie(name,'',-1);
}

window.onload=onLoad;
window.onunload=GUnload;
