// The google map object (global for resize events)
var map;

// Custom icon array
var customIcons = []

// Colored small icon
var smallIcon = new GIcon()
smallIcon.image = "http://labs.google.com/ridefinder/images/mm_20_red.png"
smallIcon.shadow = "http://labs.google.com/ridefinder/images/mm_20_shadow.png"
smallIcon.iconSize = new GSize(12, 20)
smallIcon.shadowSize = new GSize(22, 20)
smallIcon.iconAnchor = new GPoint(6, 20)
smallIcon.infoWindowAnchor = new GPoint(5, 1)

// The name of the icon to use by default
var defaultIconName = null

// Loads map data from the file '<name>.xml'
function loadMap(name)
{
  if (GBrowserIsCompatible())
  {
    if (loadMapStart)
    {
      loadMapStart(name)
    }

    var request = GXmlHttp.create()
    request.open("GET", "xml/" + name + ".xml", true)

    request.onreadystatechange = function()
    {
      if (request.readyState == 4)
      {
        if (request.responseXML.documentElement)
        {
          switch (request.responseXML.documentElement.nodeName)
          {
            case "map":
            {
              processMap(request.responseXML.documentElement)

              if (loadMapEnd)
              {
                loadMapEnd(request.responseXML.documentElement.getAttribute("title"))
              }
              break
            }

            case "redirect":
              loadMap(request.responseXML.documentElement.getAttribute("map"))
              break
              
            default:
              alert("Invalid XML root node")
              break;
          }
        }
        else
        {
          document.title = "Error loading XML data file!"
          alert(document.title)
        }
      }
    }
    request.send(null)
  }
  else
  {
    document.title = "Browser Not Compatible!"
  }
}

// Process the given map XML data
function processMap(root)
{
  defaultIconName = readAttribute(root, "icon", null)

  var typeElements = root.getElementsByTagName("maptype")
  var types = []

  for (var t = 0; t < typeElements.length; t++)
  {
    switch (typeElements[t].text)
    {
      case "map":
        types[types.length] = G_MAP_TYPE
        break
      case "satellite":
        types[types.length] = G_SATELLITE_TYPE
        break
      case "hybrid":
        types[types.length] = G_HYBRID_TYPE
        break
    }
  }

  map = new GMap(document.getElementById("map"), types)
  map.addControl(new GSmallMapControl())

  GEvent.addListener(map, "click", function(overlay, point) {
    toClip('<marker lat="' + point.y + '" lon="'+ point.x + '">')
  });

  if (types.length != 1){
    map.addControl(new GMapTypeControl());
  }

  map.centerAndZoom(
    new GPoint(
      parseFloat(root.getAttribute("lon")),
      parseFloat(root.getAttribute("lat"))
    ),
    parseInt(root.getAttribute("zoom"))
  );

  var markers = root.getElementsByTagName("marker")
  var points = []
  var lineColor = "#00FF00"
  var lineWidth = 5
  var lineOpacity = 0.5
  var currentDate = new Date()
  
  for (var i = 0; i < markers.length; i++)
  {
    var xml = markers[i]
    
    var dateString = xml.getAttribute("date")
    var visible = true
    
    if (dateString)
    {
      var date = new Date(dateString)
      visible = date <= currentDate
    }
    
    var point = new GPoint(
      parseFloat(xml.getAttribute("lon")),
      parseFloat(xml.getAttribute("lat"))
    )

    var lines = xml.getElementsByTagName("line")

    if (points.length > 0)
    {
      if (visible)
      {
        points[points.length] = point
      }

      if ((lines.length > 0) || (i == markers.length - 1) || !visible)
      {
        map.addOverlay(new GPolyline(points, lineColor, lineWidth, lineOpacity))
        points = []
      }
    }

    if (visible)
    {
      if (lines.length > 0)
      {
        lineColor = readAttribute(lines[0], "color", lineColor.toString())
        lineWidth = parseInt(readAttribute(lines[0], "width", lineWidth.toString()))
        lineOpacity = parseFloat(readAttribute(lines[0], "opacity", lineOpacity.toString()))

        switch (readAttribute(lines[0], "action", "start"))
        {
          case "start":
            points[points.length] = point
            break
        }
      }

      if (xml.getElementsByTagName("info").length > 0)
      {
        map.addOverlay(createMarker(point, xml))
      }
    }
  }

  // Update when window is resized
  if (window.attachEvent)
  {
    window.attachEvent("onresize", function() { this.map.onResize(); } )
  }
  else
  {
    window.addEventListener("resize", function() { this.map.onResize() }, false)
  }
}

// Read an attribute, or use given value if it does not exist
function readAttribute(element, name, value)
{
  var v = element.getAttribute(name)
  return (v) ? v : value
}

// Creates a single map marker from the given XML element
function createMarker(point, xml)
{
  var icon = null
  var iconName = readAttribute(xml, "icon", defaultIconName)

  if (customIcons[iconName])
  {
    icon = customIcons[iconName]
  }
  else 
  
  if (iconName != "large")
  {
    icon = new GIcon(smallIcon)
    icon.image = "http://labs.google.com/ridefinder/images/mm_20_" + iconName + ".png"
  }

  var marker = new GMarker(point, icon)

  GEvent.addListener(
    marker, "click",
    function()
    {
      marker.openInfoWindowXslt(xml, "info.xsl")
    }
  );

  return marker;
}

function toClip(text)
{
  if (window.clipboardData)
  {
    window.clipboardData.setData("Text", text)
    return true
  }

  return false
}