var latlon = {lat: 45.5234515, lon: -122.6762071, level: 'default'};
var map;
var all_results = [];
var merged_results = [];
var settings = null;
var allvisited = ";";
var tryfs = false;
var fs_results = [];

// Prepare 
$(document).ready(function() {
  $("#results").hide();
  $("#locselect").hide();
  $("#loading").hide();
  findIPLocation();
  createEvents();
  loadCookies();
});

function loadCookies() {
  // Basic settings
  settings = $.cookie("unrut_settings");
  if (settings) {
    settings = eval("("+settings+")"); // replace with JSON parser
  }
  else {
    // Create new settings object
    settings = {numvisited: 0, locations: []};
  }
  
  // Visited settings
  for (var i=1; i<=settings.numvisited; i++) {
    var thisvisited = $.cookie("unrut_visited" + i);
    allvisited += thisvisited;
  }

  // Check FourSquare
  var fs = $.cookie("fs");
  tryfs = (fs != null && fs != "");
}
function setCookies() {
  // Visited settings
  var thisvisit = "";
  var visitcount = 1;
  var visit_array = allvisited.split(";");
  for (var i=0; i<visit_array.length; i++) {
    if (visit_array[i].length > 0) {
      if (thisvisit.length > 4000) {
        $.cookie("unrut_visited" + visitcount, thisvisit, {expires: 60});
        thisvisit = "";
        visitcount++;
      }
      thisvisit += visit_array[i] + ";";
    }
  }
  if (thisvisit != "") {
    $.cookie("unrut_visited" + visitcount, thisvisit, {expires: 60});
  }
  settings.numvisited = visitcount;

  // Basic settings
  var settings_str = "{numvisited: " + settings.numvisited + ", locations: [";
  
  settings_str += "]}";
  $.cookie("unrut_settings", settings_str, {expires: 60});  
}

function createEvents() {
  $("#topsearch .loc").focus(function () {
    findLocation();
  });
  

  $("#locselect").change(function() {
    var ddopt = $("#locselect option:selected");
    if (ddopt.val() == 'typein') {
      $("#locselect").hide();
      $("#topsearch .loc").show();
    }
  });

  $(window).scroll(function() {
    $("#map").css("top", $(window).scrollTop() + "px");
  });

  $("#fsreload").click(function() {
    var currentsrc = $("#fsreload").attr('src');
    if (currentsrc == "/img/fs_reload.png") {
      $("#fsreload").attr('src', "/img/fs_reload.gif");
      loadFourSquare(latlon.lat, latlon.lon, true);
    }
    else {
      $("#fsreload").attr('src', "/img/fs_reload.png");
    }
  });
}

function addLocationOption(id, val) {
  var opt = $("<option></option>");
  opt.attr("value", id).text(val);
  opt.attr('selected', 'selected');

  $("#locselect").append(opt);
  showSearchDrop();
}
function showSearchDrop() {
  $("#topsearch .loc").hide();
  $("#locselect").show();
}
function showSearchBox() {
  $("#topsearch .loc").show();
  $("#locselect").hide();
}

function findIPLocation() {
  var iploc = google.loader.ClientLocation;
  if (iploc) {
    latlon.lat = iploc.latitude;
    latlon.lon = iploc.longitude;
    latlon.level = 'ip';

    var cityname = iploc.address.city + ", " + iploc.address.region;
    $(".loc").each(function(i, obj) {
      obj.value = cityname;
    });
  }

  // Create the map with the IP or default location (if found via other method, it will reset center)
  simpleMap();
}
function findLocation(force) {
  if (latlon.level != 'w3c' || force) {
    navigator.geolocation.getCurrentPosition(foundLocation, function() { });
  }
}
function foundLocation(pos) {
  latlon.lat = pos.coords.latitude;
  latlon.lon = pos.coords.longitude;
  latlon.level = 'w3c';
  latlon.label = 'Current location';
  addLocationOption('w3c', 'Current location', true);
  settings.locations.push(latlon);
  resetMap();
}

function simpleMap() {
  map = new mxn.Mapstraction('map', 'google');
  map.addSmallControls();
  resetMap();
}
function resetMap() {
  var zoom = 11;
  if (latlon.level == 'w3c') {
    zoom = 13;
  }
  map.setCenterAndZoom(new mxn.LatLonPoint(latlon.lat, latlon.lon), zoom);
}

function visitedClick(uid, result) {
  setVisited(uid);
  result.fadeOut("fast");
  var html = "<li>" + result.html() + "</li>";
  $(html).appendTo("#oldplaces");
  $("#oldplaces .notate:last").hide();

  // Create new marker with visited icon
  var thismk = findMarker(uid);
  var newmk = new mxn.Marker(thismk.location);
  newmk.attributes = thismk.attributes;
  newmk.setInfoBubble(thismk.infoBubble);
  newmk.setIcon('/img/old.png', [24,24]);
  newmk.setShadowIcon('/img/old-shadow.png', [36,24]);
  newmk.setAttribute('new', 0);
  map.removeMarker(thismk);
  map.addMarker(newmk);
}

function findMarker(uid) {
  for(var i=0; i< map.markers.length; i++) {
    var thismk = map.markers[i];
    if (thismk.getAttribute('id') == uid) {
      return thismk;
    }
  }
}

function setVisited(uid) {
  var visitedtext = uid + ";";
  allvisited += visitedtext;
  setCookies();
}
function isVisited(uid) {
  return (allvisited.indexOf(";" + uid + ";") > -1);
}

function mergeResults() {
  if (all_results.length == 2) {
    $("#loading").hide();
    // Set two variables
    var nextstop = all_results[0];
    var yelp = all_results[1];
    if (nextstop.length > 0 && nextstop[0].source != 'nextstop') {
      var swap = nextstop;
      nextstop = yelp;
      yelp = swap;
    }
    // Determine duplicates
    for (var nexti=0; nexti<nextstop.length; nexti++) {
      for (var yelpi=0; yelpi<yelp.length; yelpi++) {
        if (isDuplicate(nextstop[nexti], yelp[yelpi], true)) {
          if (nextstop[nexti].img.src == null || nextstop[nexti].img.src == "") {
            nextstop[nexti] = {};
          }
          else {
            yelp[yelpi] = {};
          }
        }
      }
    }
    // Perform the merge
    var results = nextstop;
    results = results.concat(yelp);
    results.sort(function(a,b){return a.dist - b.dist});
    merged_results = results;
    displayResults(results);
    markCheckins();
  }
}
function markCheckins() {
  var num_switched = 0;
  var allres = "";
  if (merged_results.length > 0 && fs_results.length > 0) {
    for (var resi=0; resi<merged_results.length; resi++) {
      if (!isVisited(merged_results[resi].uid)) {
        for (var fsi=0; fsi<fs_results.length; fsi++) {
          if (isDuplicate(merged_results[resi], fs_results[fsi], false)) {
            setVisited(merged_results[resi].uid);
	    num_switched++;
	  }
	}
      }
    }
    if (num_switched) {
      clearResults();
      displayResults(merged_results);
    }
  }
}
function displayResults(list) {
  for (var i=0; i<list.length; i++) {
    if (list[i].name != undefined) {
      displayPlaceOnMap(list[i]);
      displayPlaceInList(list[i]);
    }
  }
  map.autoCenterAndZoom();
  $("#results").show();
}
function displayPlaceOnMap(obj) {
  var mk = new mxn.Marker(obj.loc);
  mk.setAttribute('id', obj.uid);
  if (isVisited(obj.uid)) {
    mk.setIcon('/img/old.png', [24,24]);
    mk.setShadowIcon('/img/old-shadow.png', [36,24]);
    mk.setAttribute('new', 0);
  }
  else {
    mk.setIcon('/img/new.png', [24,24]);
    mk.setShadowIcon('/img/new-shadow.png', [36,24]);
    mk.setAttribute('new', 1);
  }
  mk.setInfoBubble('<strong>' + obj.name + '</strong><br />' + obj.address + '<br />' + obj.phone);
  map.addMarker(mk);
}
function displayPlaceInList(obj) {
  var whichplaces = "#newplaces";
  var beenherelink = "<a href=\"#" + obj.uid + "\" class=\"notate\">i've been here</a>";
  if (isVisited(obj.uid)) {
    whichplaces = "#oldplaces";
    beenherelink = "";
  }
  
  var newhtml = "<li><div class=\"heading\">" + beenherelink;
  newhtml += "<h3>" + obj.name + "</h3></div>";
  if (obj.img.src) {
    newhtml += "<img src=\"" + obj.img.src + "\" width=\"" + obj.img.w + "\" height=\"" + obj.img.h + "\" />";
  }
  newhtml += "<div class=\"contactinfo\"\">" + obj.address + "</div><div class=\"contactinfo\"\">" + obj.phone + "</div>";
  newhtml += "<div class=\"description\">" + obj.description + "</div>";
  newhtml += "<div class=\"credit\">by <a target=\"_blank\" href=\"" + obj.userlink + "\">" + obj.username + "</a> on <a target=\"_blank\" href=\"" + obj.link + "\">" + obj.source + "</a></div></li>";

  //$(newhtml).appendTo(whichplaces);
  var codetoadd = $(newhtml);
  codetoadd.appendTo(whichplaces);
  codetoadd.click(function() {
    var thismk = findMarker(obj.uid);
    thismk.openBubble();
  });

  $(whichplaces + " .notate:last").click(function() { 
    visitedClick(obj.uid, $(this).parent().parent());
    return false;
  });
}
function loadPlaces(f) {
  var kw = "";
  var loc = "";
  var ddopt = null;
  
  // Find keyword and location
  for (var i=0; i < f.elements.length; i++) {
    if (f.elements[i].className == 'kw') {
      kw = f.elements[i].value;
    }
    if (f.elements[i].className == 'loc') {
      loc = f.elements[i].value;
    }
    if (f.elements[i].id == 'locselect') {
      ddopt = f.elements[i].options[f.elements[i].selectedIndex];
    }
  }
  
  if (!ddopt || (ddopt && ddopt.value == 'typein')) {
    // Perform geocoding
    var geocoder = new MapstractionGeocoder(function(geoloc) {
      latlon.lat = geoloc.point.lat;
      latlon.lon = geoloc.point.lon;
      latlon.level = 'geocode';
      
      performSearch(kw, geoloc.point);
    }, 'google');
    var address = new Object();
    address.address = loc;
    geocoder.geocode(address);
    $(".loc").val(loc);
  }
  else {
    // Grab correct lat/long from locations list
    var latsearch = null;
    for (var i=0; i<settings.locations.length; i++) {
      if (ddopt.value == settings.locations[i].level) {
        latsearch = settings.locations[i];
        break;
      }
    }
    performSearch(kw, latsearch);
  }
}  
function clearResults() {
  map.removeAllMarkers();
  $("ol.results").children().remove();
  $("#results").hide();
  $("#intro").hide();
}
function performSearch(kw, llobj) {
  // Clear the decks for new search
  clearResults();
  $("#loading").show();
  all_results = [];
  
  // Call search APIs
  if (tryfs) {
    loadFourSquare(llobj.lat, llobj.lon);
  }
  loadNextStop(kw, llobj.lat, llobj.lon, 5);
  loadYelp(kw, llobj.lat, llobj.lon, 2);
  
/*
  // Add location as 'Last location'
  if($("#locselect option[value='last']").text() == '') {
    // Create last location
    addLocationOption('last', 'Last location');
    latlon.lat = llobj.lat;
    latlon.lon = llobj.lon;
    latlon.level = 'last';
    latlon.label = 'Last location';
    settings.locations.push(latlon);
  }
  else {
    // Update last location
    var latsearch = null;
    for (var i=0; i<settings.locations.length; i++) {
      if (settings.locations[i].level == 'last') {
        settings.locations[i].lat = llobj.lat;
        settings.locations[i].lon = llobj.lon;
        showSearchDrop();
        break;
      }
    }

  }
*/
}
function loadFourSquare(lat, lon, force) {
  fs_results = [];
  var fs_json = $.cookie("fs_results");
  if ((fs_json == "" || fs_json == null) || force) {
    $.get("/fs/get.php", function(json) {
      $.cookie("fs_results", json, {expires: 60});
      $("#fsreload").attr('src', "/img/fs_reload.png");
      parseFourSquare(lat, lon, json);
    });
  }
  else {
    parseFourSquare(lat, lon, fs_json);
  }
}
function parseFourSquare(lat, lon, json) {
  json = eval('('+json+')');

  var searchLoc = new mxn.LatLonPoint(lat, lon);
  for (var i = 0; i < json.length; i++) {
    var place = json[i];
    var thisloc = new mxn.LatLonPoint(place.geolat, place.geolong);
    var obj = {source: 'foursquare', uid: place.id, name: place.name, address: place.address, phone: formatPhone(place.phone), loc: thisloc, dist: thisloc.distance(searchLoc), addrnum: extractAddressNumber(place.address)};
    fs_results.push(obj);
  }
  markCheckins();
}
function loadNextStop(kw, lat, lon, rad) {
  var url = "http://api.nextstop.com/search/";
  url += "?key=2SUKuZ51st0g9xkVz";
  url += "&result_type=places";
  url += "&keywords=" + kw;
  url += "&lat=" + lat + "&lng=" + lon + "&rad=" + rad;
  url += "&callback=?";
  
  var searchLoc = new mxn.LatLonPoint(lat, lon);
  
  $.getJSON(url, function(x) {
    var nextstop_array = [];
    if (x.status == 200) {
      if (x.data != null) {
        var res = x.data.resultsList;

        var all = "";
        for (var i = 0; i < res.length; i++) {
          var place = res[i];
          if (place.geoAccuracy == "point") {
            all += place.name + "(" + place.address + ")\n";
            var thisloc = new mxn.LatLonPoint(place.lat, place.lng);
            var id = place.permalink.match("\/p\/([^\/]*)\/");
            if (id.length > 1) {
              id = id[1];
            }
            var obj = {source: 'nextstop', uid: id, name: place.name, address: place.address, phone: formatPhone(place.phone), img: {src: place.recommendationsInfo.bestRecommendation.smallCachedImageUrl, w: 150, h: 150}, description: place.recommendationsInfo.bestRecommendation.shortText, loc: thisloc, dist: thisloc.distance(searchLoc), addrnum: extractAddressNumber(place.address), link: place.recommendationsInfo.bestRecommendation.permalink, username: place.recommendationsInfo.bestRecommendation.authorInfo.authorName, userlink: place.recommendationsInfo.bestRecommendation.authorInfo.authorUrl};
			nextstop_array.push(obj);
          }
        }

      }
    }
    all_results.push(nextstop_array);
    mergeResults();
  });
}
function loadYelp(kw, lat, lon, rad) {
  var url = "http://api.yelp.com/business_review_search";
  url += "?ywsid=KThzbeyMbC3Z7iMzNujutw";
  url += "&num_biz_requested=10";
  url += "&term=" + kw;
  url += "&lat=" + lat + "&long=" + lon + "&radius=" + rad;
  url += "&callback=?";
  
  var searchLoc = new mxn.LatLonPoint(lat, lon);
  
  $.getJSON(url, function(x) {
    var yelp_array = [];
    if (x.message.text == "OK") {
      if (x.businesses.length != 0) {
        var res = x.businesses;

        var all = "";
        for (var i = 0; i < res.length; i++) {
          var place = res[i];
          all += place.name + "(" + place.address1 + ")\n";
          var thisloc = new mxn.LatLonPoint(place.latitude, place.longitude);
          var id = place.id;
          var obj = {source: 'yelp', uid: id, name: place.name, address: place.address1, phone: formatPhone(place.phone), img: {src: place.photo_url, w: 100, h: 100}, description: place.reviews[0].text_excerpt, loc: thisloc, dist: thisloc.distance(searchLoc), addrnum: extractAddressNumber(place.address1), link: place.url, username: place.reviews[0].user_name, userlink: place.reviews[0].user_url};
		  yelp_array.push(obj);
        }

      }
    }
    all_results.push(yelp_array);
    mergeResults();
  });
}

function isDuplicate(nobj, yobj, withaddr) {
  if (nobj == null || yobj == null) {
    return false;
  }
  if (!withaddr || (nobj.addrnum == yobj.addrnum)) {
    if (nobj.loc.distance(yobj.loc) < .1) {
      var lcs = longestCommonSubstring(nobj.name, yobj.name);
      if (lcs.length > 2) {
        return true;
      }
    }
  }
  return false;
}
function formatPhone(phone) {
  if (!phone) { return; }
  phone = phone.replace(/[\D]*/g, '');
  if (phone.length == 10) {
    phone = "(" + phone.substr(0, 3) + ") " + phone.substr(3, 3) + "-" + phone.substr(6, 4);
  }
  if (phone.length == 7) {
    phone = phone.substring(0, 3) + "-" + phone.substring(3, 4);
  }
  return phone;
}
function extractAddressNumber(address) {
  var numbers = address.match("[0-9]+");
  if (numbers) {
    return numbers[0];
  }
  return null;
}
function longestCommonSubstring(first, second) {
  var ftokens = first.split(" ");
  var stokens = second.split(" ");
  
  var longest = "";
  for (var o=0; o<ftokens.length; o++) {
    for (var i=0; i<stokens.length; i++) {
      if (ftokens[o].indexOf(stokens[i]) > -1) {
        if (stokens[i].length > longest.length) {
          longest = stokens[i];
        }
      }
      if (stokens[i].indexOf(ftokens[o]) > -1) {
        if (ftokens[o].length > longest.length) {
          longest = ftokens[o];
        }
      }
    }
  }
  return longest;
}



// FOR DEBUGGING
function inspect(obj, maxLevels, level)
{
  var str = '', type, msg;

    // Start Input Validations
    // Don't touch, we start iterating at level zero
    if(level == null)  level = 0;

    // At least you want to show the first level
    if(maxLevels == null) maxLevels = 1;
    if(maxLevels < 1)     
        return '<font color="red">Error: Levels number must be > 0</font>';

    // We start with a non null object
    if(obj == null)
    return '<font color="red">Error: Object <b>NULL</b></font>';
    // End Input Validations

    // Each Iteration must be indented
    str += '<ul>';

    // Start iterations for all objects in obj
    for(property in obj)
    {
      try
      {
          // Show "property" and "type property"
          type =  typeof(obj[property]);
          str += '<li>(' + type + ') ' + property + 
                 ( (obj[property]==null)?(': <b>null</b>'):('')) + '</li>';

          // We keep iterating if this property is an Object, non null
          // and we are inside the required number of levels
          if((type == 'object') && (obj[property] != null) && (level+1 < maxLevels))
          str += inspect(obj[property], maxLevels, level+1);
      }
      catch(err)
      {
        // Is there some properties in obj we can't access? Print it red.
        if(typeof(err) == 'string') msg = err;
        else if(err.message)        msg = err.message;
        else if(err.description)    msg = err.description;
        else                        msg = 'Unknown';

        str += '<li><font color="red">(Error) ' + property + ': ' + msg +'</font></li>';
      }
    }

      // Close indent
      str += '</ul>';

    return str;
}