// Marker icon objects.
var map_icons = map_icons_init();
// Marker objects.
var markers_arr = [];
$(window).unload(function() {
  for (var i = 0, len = markers_arr.length; i < len; i++) {
    markers_arr[i].setMap(null);
  }
  map_icons = null;
});

// Default map options
var def_options = {
    zoom: 14,
    mapTypeControl: true,
    mapTypeControlOptions: {style: google.maps.MapTypeControlStyle.DROPDOWN_MENU},
    navigationControl: false,
    scaleControl: false,
    scrollwheel: false,
    mapTypeId: google.maps.MapTypeId.ROADMAP
};

function load_google_map(url, name, site, addr, lat, lng, theme) {
    function formatInfoText() {
        var label = '<div style="padding-bottom: 2px; font-size:12px; font-family: arial;">' + name + '<small>';
        if (site != "") {
            label += '<br />' + site;
        }
        label += '<br />' + addr;
        label += '<br /><a target="_blank" href="/cgi-bin/redir.cgi?' + url + '">Visit Event Website</a></small></div>';
        return label;
    }
    // Create map object.
    var def_center = new google.maps.LatLng(lat, lng);
    def_options['center'] = def_center;
    var map_obj = new google.maps.Map(document.getElementById("map_canvas"), def_options);
    // Add custom control.
    var ren_control = new RenControl(map_obj, def_center);
    map_obj.controls[google.maps.ControlPosition.TOP_LEFT].push(ren_control);

    // Add marker.
    map_add_marker(map_obj, def_center, {
        title: name,
        active: false,
        openwindow: true,
        theme: theme,
        infotext: formatInfoText()
    });
}

function load_states_map(options) {
    var def_center;
    if (options.lat) {
        def_center = new google.maps.LatLng(options.lat, options.lng);
    } else {
        def_center = new google.maps.LatLng(44.576774,-113.621979);
    }
    def_options['center'] = def_center;
    if (options.stateabbr) {
        def_options['zoom'] = 6;
    } else {
        def_options['zoom'] = 3;
    }
    // Create map object.
    var map_obj = new google.maps.Map(document.getElementById("map_canvas"), def_options);
    // Add custom control.
    var ren_control = new RenControl(map_obj, def_center);
    map_obj.controls[google.maps.ControlPosition.TOP_LEFT].push(ren_control);

    // Yield and update marker set.
    setTimeout(function(){ load_state_markers(map_obj, options); }, 100);
}


function load_state_markers(map_obj, options) {
    var marker_obj = new MarkerSet(map_obj);
    var list = new Array();

    // Fetch list and display markers.
    var gen_geo_url = "/Sites/json_gen_geo.cgi";
    // XXX - limit to state omits bordering states.
    //if (options.stateabbr) {
    //  gen_geo_url += "?state=" + options.stateabbr;
    //}
    $.getJSON(gen_geo_url, function(data) {
	function formatUrl(id, title, state) {
		return '/Sites/' + nicename(state) + '/' + nicename(title) + '.' + id + '.html';
	}
        function formatInfoText(url, title, city, state, stateabbr) {
            return '<div style="padding-bottom: 2px; font-size:12px; font-family: arial;"><small><a href="' + url + '">' + title + '</a><br />' + city + ', ' + stateabbr + '</small></div>';
	}
	function nicename(str) {
		str = str.replace(/\s*&(amp;)?\s*/g, ' and ');
		str = str.replace(/\s+/g, '-');
		str = str.replace(/[^-\w]+/g, '');
		return(str);
	}
	var $fairelist = $('#fairelist');
        var bounds = new google.maps.LatLngBounds();
        var len = data.markers.length;
        for (var i = 0; i < len; i++) {
            with(data.markers[i]) {
              var state_abbr = stateabbr;
              var loc = new google.maps.LatLng(lat, lng);
              var url = formatUrl(id, title, state);
              var opts = {
                title: title,
                active: active,
                openwindow: false,
                theme: theme,
                infotext: formatInfoText(url, title, city, state, stateabbr),
                zIndex: 1+active
              };
              var link = '<a href="' + url + '">' + title + '</a> - ' + city + '<br />';
            }

            // Extend the map bounds to fit the marker.
            if (state_abbr === options.stateabbr) {
                bounds.extend(loc);
                map_add_marker(map_obj, loc, opts);
                $fairelist.append(link);
            } else {
              list.push({loc: loc, opts: opts});
            }
        }
	marker_obj.setList(list);

        if (!bounds.isEmpty()) {
            // Resize the map to fit the markers, but not too zoomy.
            var listener = google.maps.event.addListener(map_obj, "bounds_changed", function() {
                google.maps.event.removeListener(listener);
                // Limit max zoom.
                if (map_obj.getZoom() > 10) {
                  map_obj.setZoom(10);
                }
                // Set the center point for recentering 
                def_center = map_obj.getCenter();
            });
            map_obj.fitBounds(bounds);
        }
        bounds = null;
	marker_obj.renderAll(5);
    });
}

//======================================================================
// XXX - if markers overlap, merge to a single infowindow
function map_add_marker(map_obj, loc, options) { 
    // Theme => marker mapping
    // See xml_cgi for definition of theme.
    var icon_name = "faire";
    switch(options.theme) {
        case "":
            icon_name = "faire";
            break;
        case "Pirates":
            icon_name = "pirate";
            break;
        case "Fairies":
            icon_name = "fairy";
            break;
        case "Dickens":
            icon_name = "dickens";
            break;
	case "Celtic":
	case "Highland Games":
            icon_name = "celtic";
            break;
        default:
            icon_name = "faire";
    }
    if (! options.active) {
        icon_name += "_sm";
    }

    var icon_obj = map_icons[icon_name];

    // Add marker.
    var marker = new google.maps.Marker({
        position: loc,
        map: map_obj,
        title: options.title,
        icon: icon_obj,
	visible: true,
	zIndex: options.zIndex
    });
    markers_arr.push(marker);

    // Add info window
    var infowindow = new google.maps.InfoWindow({
        content: options.infotext
    });

    // Open by default.
    if (options.openwindow) {
      infowindow.open(map_obj, marker);
    }

    // Open on click.
    google.maps.event.addListener(marker, "click", function() {
      infowindow.open(map_obj, marker);
    });

}

//======================================================================
function map_icons_init() {

  var map_icon_faire_sm = new google.maps.MarkerImage(
      "/images/mapcontrols/icon_15x21_sprites.png",
      new google.maps.Size(15, 21),
      new google.maps.Point(0, 0),
      new google.maps.Point(7, 21)
  );

  var map_icon_faire = new google.maps.MarkerImage(
      "/images/mapcontrols/icon_31x35_sprites.png",
      new google.maps.Size(31, 35),
      new google.maps.Point(0, 0),
      new google.maps.Point(16, 35)
  );

  // Pirate
  var map_icon_pirate_sm = new google.maps.MarkerImage(
      "/images/mapcontrols/icon_15x21_sprites.png",
       new google.maps.Size(15, 21),
       new google.maps.Point(15, 0),
       new google.maps.Point(7, 21)
  );

  var map_icon_pirate = new google.maps.MarkerImage(
      "/images/mapcontrols/icon_31x35_sprites.png",
      new google.maps.Size(31, 35),
      new google.maps.Point(31, 0),
      new google.maps.Point(16, 35)
  );

  // Fairy
  var map_icon_fairy_sm = new google.maps.MarkerImage(
      "/images/mapcontrols/icon_15x21_sprites.png",
      new google.maps.Size(15, 21),
      new google.maps.Point(30, 0),
      new google.maps.Point(7, 21)
  );

  var map_icon_fairy = new google.maps.MarkerImage(
      "/images/mapcontrols/icon_31x35_sprites.png",
      new google.maps.Size(31, 35),
      new google.maps.Point(62, 0),
      new google.maps.Point(16, 35)
  );

  // Dickens
  var map_icon_dickens_sm = new google.maps.MarkerImage(
      "/images/mapcontrols/icon_15x21_sprites.png",
      new google.maps.Size(15, 21),
      new google.maps.Point(45, 0),
      new google.maps.Point(7, 21)
  );

  var map_icon_dickens = new google.maps.MarkerImage(
      "/images/mapcontrols/icon_31x35_sprites.png",
      new google.maps.Size(31, 35),
      new google.maps.Point(93, 0),
      new google.maps.Point(16, 35)
  );

  // Celtic
  var map_icon_celtic_sm = new google.maps.MarkerImage(
      "/images/mapcontrols/icon_15x21_sprites.png",
      new google.maps.Size(15, 21),
      new google.maps.Point(60, 0),
      new google.maps.Point(7, 21)
  );

  var map_icon_celtic = new google.maps.MarkerImage(
      "/images/mapcontrols/icon_31x35_sprites.png",
      new google.maps.Size(31, 35),
      new google.maps.Point(124, 0),
      new google.maps.Point(16, 35)
  );

  return {
    faire: map_icon_faire,
    faire_sm: map_icon_faire_sm,
    pirate: map_icon_pirate,
    pirate_sm: map_icon_pirate_sm,
    fairy: map_icon_fairy,
    fairy_sm: map_icon_fairy_sm,
    dickens: map_icon_dickens,
    dickens_sm: map_icon_dickens_sm,
    celtic: map_icon_celtic,
    celtic_sm: map_icon_celtic_sm
  };
}

//======================================================================
// Marker Display control.

function MarkerSet(map_obj) {
    this.map = map_obj;
    this.list = null;
    this.last = 0;
    this.len = 0;
}

MarkerSet.prototype.setList = function(list) {
    this.list = list;
    this.last = 0;
    this.len = list.length;
}

MarkerSet.prototype.clearList = function() {
    this.list = null;
    this.last = 0;
    this.len = 0;
}

MarkerSet.prototype.render = function(n) {
    for (var i = this.last, j = 0; i < this.len && j < n; i++, j++) {
      var obj = this.list[i];
      map_add_marker(this.map, obj.loc, obj.opts);
    }
    this.last += n;
}

MarkerSet.prototype.renderAll = function(n) {
    if (this.last < this.len) {
      this.render(n);
      var self = this;
      setTimeout(function(){ self.renderAll.call(self, n); }, 200);
    }
}

//======================================================================
// Custom navigation control.

function RenControl(map, def_center) {
    this.def_center = def_center;
    var div = this.initialize(map);
    return(div);
}

//RenControl.prototype.getCenter = function() {
//    return this.def_center;
//}
//RenControl.prototype.setCenter = function(def_center) {
//    this.def_center = def_center;
//}

// Creates a one DIV for each of the buttons and places them in a container
// DIV which is returned as our control element. We add the control to
// to the map container and return the element for the map class to
// position properly.
RenControl.prototype.initialize = function(map) {
  var is_ie = /MSIE [5678]/.test(navigator.userAgent) && navigator.platform == "Win32";
  var obj = document.createElement("div");
  if (is_ie) {
    var trans_div = document.createElement("div");
    trans_div.style.filter = "progid:DXImageTransform.Microsoft.AlphaImageLoader(src='/images/mapcontrols/uber_rose3.png', sizingMethod='crop')";
    trans_div.src = "/images/mapcontrols/uber_rose3.png";
    trans_div.style.border = "0px none";
    trans_div.style.padding = "0px";
    trans_div.style.width = "75px";
    trans_div.style.height = "119px";
    var Img = document.createElement("img");
    Img.src = "/images/mapcontrols/uber_rose3.png";
    Img.style.visibility = "hidden";
    trans_div.appendChild(Img);
    obj.appendChild(trans_div);
  } else {
    var Img = document.createElement("img");
    Img.src = "/images/mapcontrols/uber_rose3.png";
    Img.style.border = "0px none";
    Img.style.padding = "0px";
    Img.style.position = "absolute";
    Img.style.left = "0px";
    Img.style.right = "0px";
    Img.style.width = "75px";
    Img.style.height = "119px";
    Img.style.MozUserSelect = "none";
    obj.appendChild(Img);
  }

//  this.createCenter(map, obj, is_ie, "Recenter", 20+8, 20+35);

  this.createPan(map, obj, is_ie, "Pan NW", 0+8, 0+35);
  this.createPan(map, obj, is_ie, "Pan N", 20+8, 0+30);
  this.createPan(map, obj, is_ie, "Pan NE", 40+8, 0+35);

  this.createPan(map, obj, is_ie, "Pan W", 0+2, 20+35);

  this.createPan(map, obj, is_ie, "Pan E", 40+13, 20+35);

  this.createPan(map, obj, is_ie, "Pan SW", 0+8, 40+35);
  this.createPan(map, obj, is_ie, "Pan S", 20+8, 40+40);
  this.createPan(map, obj, is_ie, "Pan SE", 40+8, 40+35);

  this.createZoom(map, obj, is_ie, "Zoom Out", 0+3, 40+60);
  this.createZoom(map, obj, is_ie, "Zoom In", 40+8, 40+60);

  return(obj);
}

RenControl.prototype.createControl = function(obj, is_ie, title, L, T) {
  var div = document.createElement("div");
  obj.appendChild(div); 
  div.title = title;
  div.style.position = "absolute";
  div.style.left = L + "px";
  div.style.top = T + "px";
  div.style.width = "18px";
  div.style.height = "18px";
  div.style.cursor = "pointer";
  //div.style.border = "1px white solid";
  if (is_ie) {
    div.style.backgroundColor = "white";
    div.style.filter = "alpha(opacity=1)";
  }
  return(div);
}

//RenControl.prototype.createCenter = function(map, obj, is_ie, title, L, T) {
//  var div = this.createControl(obj, is_ie, title, L, T);
//(function(map, div, self) {
//  google.maps.event.addDomListener(div, "click", function() {
//      map.setCenter(self.getCenter());
//  });
//})(map, div, this);
//}

RenControl.prototype.createPan = function(map, obj, is_ie, title, L, T) {
  var div = this.createControl(obj, is_ie, title, L, T);
  var panx = 0; if (L < 20) { panx = -1; } else if (L > 40) { panx = 1; }
  var pany = 0; if (T < 40) { pany = 1; } else if (T > 60) { pany = -1; }
(function(map, div, panx, pany) {
  google.maps.event.addDomListener(div, "click", function() {
    var center = map.getCenter();
    var corner = map.getBounds().getSouthWest();
    var delta_lat = pany * 0.5 * (center.lat() - corner.lat());
    var delta_lng = panx * 0.5 * (center.lng() - corner.lng());
    var new_center = new google.maps.LatLng(center.lat() + delta_lat, center.lng() + delta_lng);
    map.panTo(new_center);
  });
})(map, div, panx, pany);
}

RenControl.prototype.createZoom = function(map, obj, is_ie, title, L, T) {
  var div = this.createControl(obj, is_ie, title, L, T);
(function(map, div, title) {
  google.maps.event.addDomListener(div, "click", function() {
    if (title == "Zoom In") {
      map.setZoom(map.getZoom()+1);
    } else {
      map.setZoom(map.getZoom()-1);
    }
  });
})(map, div, title);
}
