﻿if (GBrowserIsCompatible())
{
   var SOUTH_LABEL = "Sørgående";
   var NORTH_LABEL = "Nordgående";
   var INACTIVE_LABEL = "Ikke aktiv";

   // set isSouthbound function hvis retning skal vises
   var isSouthbound = null;
   var inactiveVesselTimeDiff = 3600000;
   var placeMarkerFile;
   var vesselMarkerFile;
   var vesselInfoFile;
   // this variable will collect the html which will eventualkly be placed in the sidebar
   var sidebar_html = "";

   var vesselMarkerMap = new HashMap();
   var vesselInfoMap = new HashMap();
   var featureAttributes = new HashMap();
   var textAttributes = new HashMap();

   var selectedVesselId = null;
   var vesselInfoDone = false;
   var vesselMarkerParseTries = 0;
   var vesselMarkerData = null;
   var vesselInfoData = null;
   var map = null;
   var mapElID = "IDmap";
   var sidebarElID = "IDsidebar";
   var lastTimeElID = "IDlastUpdateValue";

   // Create our vessel marker icons
   var baseIconSouth = new GIcon();
   var baseIconNorth = new GIcon();

   // Create our place marker icon
   var basePlaceIcon = new GIcon();

   function initGMap(aPlaceMarkerFile, aVesselInfoFile, aVesselMarkerFile, aMapElID, aSidebarElID, aLastTimeElID)
   {
      if (aPlaceMarkerFile && aPlaceMarkerFile.length > 0) placeMarkerFile = aPlaceMarkerFile;
      if (aVesselInfoFile && aVesselInfoFile.length > 0) vesselInfoFile = aVesselInfoFile;
      if (aVesselMarkerFile && aVesselMarkerFile.length > 0) vesselMarkerFile = aVesselMarkerFile;

      if (aMapElID && aMapElID.length > 0) mapElID = aMapElID;
      if (aSidebarElID && aSidebarElID.length > 0) sidebarElID = aSidebarElID;
      if (aLastTimeElID && aLastTimeElID.length > 0) lastTimeElID = aLastTimeElID;

      // Set icon values
      setIconValues(baseIconSouth, "img/ship_south.png", 47, 11, 1, 6);
      setIconValues(baseIconNorth, "img/ship_north.png", 47, 11, 47, 6);
      setIconValues(basePlaceIcon, "img/Place_icon.gif", 10, 10, 5, 5);

      // Create the map
      var mapContainerRef = document.getElementById(mapElID);
      map = new GMap2(document.getElementById(mapElID));
      map.setCenter(new GLatLng(65.3,17.7),5);
      map.addControl(new GLargeMapControl());
      map.addControl(new GMapTypeControl());
      map.addControl(new GScaleControl());
      var ovcontrol = new GOverviewMapControl(new GSize(150, 150));
      map.addControl(ovcontrol, new GControlPosition(G_ANCHOR_BOTTOM_RIGHT, new GSize(0, 0)));
      new GKeyboardHandler(map);
      map.enableDoubleClickZoom();
      map.enableContinuousZoom();

      var overviewRef = document.getElementById(mapElID + "_overview");
      // mulig bug. sjekk null verdi 07.12.07
      if (overviewRef != null)
      {
         mapContainerRef.appendChild(overviewRef);

         var ovleft = getLayerWidth(mapContainerRef) - getLayerWidth(overviewRef);
         var ovtop = getLayerHeight(mapContainerRef) - getLayerHeight(overviewRef);

         overviewRef.style.left = ovleft + "px";
         overviewRef.style.top = ovtop + "px";
      }

      GEvent.addListener(map, "infowindowclose", function()
      {
         selectedVesselId = null;
      });
   }

   function setIconValues(iconRef, src, width, height, anchorX, anchorY)
   {
      iconRef.image = src;
      iconRef.shadow = "img/transparent.png";
      iconRef.iconSize = new GSize(width, height);
      iconRef.shadowSize = new GSize(1, 1);
      iconRef.iconAnchor = new GPoint(anchorX, anchorY);
      iconRef.infoWindowAnchor = new GPoint(width / 2, height / 2);
   }

   function setSouthboundMethod(funk)
   {
      isSouthbound = funk;
   }

   function setInactiveTimeDiffMillies(aInactiveTimeDiff)
   {
      if (aInactiveTimeDiff && aInactiveTimeDiff > 0)
      {
         inactiveVesselTimeDiff = aInactiveTimeDiff;
      }
   }

   function getSouthIcon()
   {
      return baseIconSouth;
   }

   function getNorthIcon()
   {
      return baseIconNorth;
   }

   function getPlaceIcon()
   {
      return basePlaceIcon;
   }

   function initMarkers()
   {
      if (typeof ActiveXObject != "undefined")
      {
         // IE workaround for handling of ISO-8859-1 encoding
         var reqObj = new requestObject();
         reqObj.downloadXML(placeMarkerFile, parsePlaceMarkerXML);
      }
      else
      {
         GDownloadUrl(placeMarkerFile, parsePlaceMarkerXML);
      }

      refreshVesselMarkers();
   }

   function refreshVesselTimestamp()
   {
      try
      {
         GDownloadUrl("import?request=lastUpdateTimestamp&filename=" + vesselMarkerFile, getTimeStampInfo);
      }
      catch(err)
      {
      }
   }


   function getTimeStampInfo(data, responseCode)
   {
      try
      {
         if (!isNaN(data - 0))
         {
            var luTimestamp = data - 0;

            var textDivRef = document.getElementById(lastTimeElID);
            if (luTimestamp > 0 && textDivRef)
            {
               textDivRef.innerHTML = getDateTimeString(luTimestamp);
            }
         }
      }
      catch(err)
      {
         //         alert(err);
      }
   }

   function setTextAttributes()
   {
      try
      {
         if (textAttributes && textAttributes.length() > 0)
         {
            var keys = textAttributes.getKeys();
            for (var i = 0; i < keys.length; i++)
            {
               var attID = keys[i];
               var attLabel = textAttributes.get(attID);
               var descRef = document.getElementById(attID);
               if (descRef)
               {
                  if (descRef.value)
                  {
                     descRef.value = attLabel;
                  }
                  else
                  {
                     descRef.innerHTML = attLabel;
                  }
               }
            }
         }
      }
      catch(err)
      {
         //         alert(err);
      }
   }

   function refreshVesselMarkers()
   {
      vesselInfoDone = false;

      if (typeof ActiveXObject != "undefined")
//         if (false)
      {
         // IE workaround for handling of ISO-8859-1 encoding
         var reqObj = new requestObject();
         reqObj.downloadXML(vesselInfoFile, handleVesselInfoData);

         var reqObj2 = new requestObject();
         reqObj2.downloadXML(vesselMarkerFile, handleVesselMarkerData);
      }
      else
      {
         GDownloadUrl(vesselInfoFile, handleVesselInfoData);
         GDownloadUrl(vesselMarkerFile, handleVesselMarkerData);
      }
      refreshVesselTimestamp();
   }

   function handleVesselMarkerData(data, responseCode)
   {
      if (data)
      {
         vesselMarkerData = data;
      }
      parseVesselMarkerXML();
   }

   function handleVesselInfoData(data, responseCode)
   {
      if (data)
      {
         vesselInfoData = data;
      }
      parseVesselInfoXML();
   }

   // Creates our vessel marker at the given point
   function createVesselMarker(point, id, label, title, destination, description)
   {
      //      alert("createVesselMarker: " + label);
      var vIcon = baseIconSouth;
      var vInfo = vesselInfoMap.get(id);
      if (toBergen(destination))
      {
         vIcon = (vInfo && vInfo.southIcon) ? vInfo.southIcon : new GIcon(baseIconSouth);
      }
      else
      {
         vIcon = (vInfo && vInfo.northIcon) ? vInfo.northIcon : new GIcon(baseIconNorth);
      }
      var html = "<div style=\"font-family:verdana;font-size:10px;\"><b>" + title + "</b><br/>" + description + "</div>";

      var marker = new GMarker(point, vIcon);
      map.addOverlay(marker);
      marker.id = id;
      marker.label = label;
      marker.description = description;
      marker.html = html;
      vesselMarkerMap.put(marker.id, marker);

      GEvent.addListener(marker, "click", function()
      {
         vesselSelected(marker.id);
      });

      createVesselMarkerInfo(id);

      return marker;
   }

   function createVesselMarkerInfo(id)
   {
      var marker = vesselMarkerMap.get(id);
      if (!marker) return;
      var vesselInfo = vesselInfoMap.get(id);
      if (!vesselInfo) return;

      var html = "<div style=\"font-family:verdana;font-size:10px;\"><b>" + marker.label + "</b><br/>";
      html += "<table>"
      html += "<tr>"
      html += "<td>"
      html += '<a href="javascript:openLargeImage(' + "'" + vesselInfo.img + "', " + "'" + id + "'" + ')" style="text-decoration:none;">';
      html += '<img src="' + vesselInfo.img + '" border="0" height="120" width="160" hspace=0 vspace=0 align="left" alt="" style="margin-right: 5px;">';
      html += "</a>"
      html += "</td>"
      html += "<td>"
      html += marker.description;
      html += "</td>"
      html += "</tr>"
      html += "<tr>"
      html += "<td colspan=2>"
      html += vesselInfo.description;
      html += "</td>"
      html += "</tr>"
      html += "</table>"
      html += "</div>";

      vesselInfo.html = html;
      vesselInfoMap.put(id, vesselInfo);
   }

   function openLargeImage(imgName, id)
   {
      var name = "";
      if (id)
      {
         var vesselInfo = vesselInfoMap.get(id);
         if (vesselInfo)
         {
            name = encodeURI(vesselInfo.label);
         }
      }
      var urlStr = 'ImgPopup.jsp?imageLabel=' + name + '&imageUrl=' + imgName;
      window.open(urlStr, "Hurtigruten", "scrollbars=yes, resizable=yes, toolbar=no, location=no, directories=no, status=no, menubar=no, copyhistory=no");
   }

   function setSenter(id)
   {
      map.closeInfoWindow();
      var marker = vesselMarkerMap.get(id);
      map.setCenter(marker.getPoint());
   }

   // This function picks up the click and opens the corresponding info window
   function vesselSelected(id)
   {
      // force map to close infoWindow to ensure that selectedVesselId is not set to null after this method
      map.closeInfoWindow();
      var marker = vesselMarkerMap.get(id);

      var vInfo = vesselInfoMap.get(id);
      if (vInfo == null)
      {
         vInfo = new VesselInfo();
         vInfo.id = id;
         vInfo.html = marker.html;
      }
      if (!vInfo.html) vInfo.html = marker.html;
      marker.openInfoWindowHtml(vInfo.html);
      selectedVesselId = id;
   }

   // Creates one of our place markers at the given point
   function createPlaceMarker(point, label, iconName, description)
   {
      var placeIcon = new GIcon(basePlaceIcon);
      placeIcon.image = iconName;
      var marker = new GMarker(point, placeIcon);
      map.addOverlay(marker);
      if (description && description.length > 0)
      {
         GEvent.addListener(marker, "click", function()
         {
            marker.openInfoWindowHtml("<div style=\"font-family:verdana;font-size:10px;\"><b>" + label + "</b><br/>" + description + "</div>");
         });
      }
   }

   function getVesselDescription(nameValueArr)
   {
      var desc = "";
      if (nameValueArr && nameValueArr.length > 0)
      {
         desc += '<table>';
         for (var i = 0; i < nameValueArr.length; i++)
         {
            try
            {
               var nameValItem = nameValueArr[i];
               desc += '<tr><td style="text-align:left;">' + nameValItem.id + '&nbsp;</td><td>' + nameValItem.value + '</td></tr>';
            }
            catch (err)
            {
            }
         }
         desc += '</table>';

      }
      return desc;
   }


   function parsePlaceMarkerXML(data, responseCode)
   {
//      return;
      var xmlDoc;
      if (data && data.documentElement)
      {
         xmlDoc = data;
      }
      if (data && data.length > 0 && !data.documentElement)
      {
         xmlDoc = GXml.parse(data);
      }

      if (xmlDoc && xmlDoc.documentElement)
      {
         var folder = getElements(xmlDoc.documentElement, "Folder");
         var places = getElements(folder[0], "Placemark");
         for (var i = 0; i < places.length; i++)
         {
            try
            {
               var pointEl = getElements(places[i], "Point");
               var coordsVal = getElementValue(pointEl[0], "coordinates");
               if (coordsVal.length == 0)
               {
                  // Skip places without coordinates
                  continue;
               }
               var coordsArr = coordsVal.split(",");

               var placeName = getElementValue(places[i], "name");

               var styleEl = getElements(places[i], "Style");
               var iconStyleEl = getElements(styleEl[0], "IconStyle");
               var iconEl = getElements(iconStyleEl[0], "Icon");
               var iconName = getElementValue(iconEl[0], "href");

               var descVal = getElementValue(places[i], "description");

               createPlaceMarker(new GLatLng(coordsArr[1] - 0, coordsArr[0] - 0), placeName, iconName, descVal);
            }
            catch(err)
            {
               //                  alert(err);
            }
         }
      }
   }

   function parseVesselMarkerXML()
   {
      if (!vesselInfoDone && vesselMarkerParseTries < 5)
      {
         vesselMarkerParseTries++;
         clearTimeout();
         setTimeout(parseVesselMarkerXML, 200);
      }
      vesselMarkerParseTries = 0;
      var data = vesselMarkerData;
      var timeNow = new Date().getTime();
      var selectedId = selectedVesselId;
      removeVesselMarkers();
      sidebar_html = "";

      var xmlDoc;
      if (data && data.documentElement)
      {
         xmlDoc = data;
      }
      if (data && data.length > 0 && !data.documentElement)
      {
         xmlDoc = GXml.parse(data);
      }

      if (xmlDoc && xmlDoc.documentElement)
      {
         var vessels = getElements(xmlDoc.documentElement, "Ais_Target");
         var sidebarArray = new Array();
         for (var i = 0; i < vessels.length; i++)
         {
            try
            {
               var vesselId = getElementValue(vessels[i], "MMSI");
               var vesselLat = getElementValue(vessels[i], "Decimal_Latitude");
               var vesselLong = getElementValue(vessels[i], "Decimal_Longitude");
               var vesselName = getElementValue(vessels[i], "Ship_name")
               var vesselDest = getElementValue(vessels[i], "Destination")
               var timeStamp = getElementValue(vessels[i], "Time_stamp");

               if (vesselLat.length == 0 || vesselLong.length == 0)
               {
                  // Skip vessels with missing position
                  continue;
               }
               var time = parseWMSFormattedDate(timeStamp);
               var isInactive = time && (timeNow - time > inactiveVesselTimeDiff);

               var vesselDirection = null;

               //                  if (toBergen(vesselDest))
               if (isSouthbound)
               {
                  if (isSouthbound(vesselDest))
                  {
                     vesselDirection = SOUTH_LABEL;
                  }
                  else
                  {
                     vesselDirection = NORTH_LABEL;
                  }
               }

               // Build vessel description table
               var descriptionAtts = new Array();
               var keys = featureAttributes.getKeys();
               for (var j = 0; j < keys.length; j++)
               {
                  var fAttObj = featureAttributes.get(keys[j]);
                  var aElVal = getElementValue(vessels[i], fAttObj.id);
                  if (aElVal)
                  {
                     if (fAttObj.id == "Time_stamp" && time)
                     {
                        var timeStr = getDateTimeString(time);
                        if (timeStr) aElVal = timeStr;
                     }
                     descriptionAtts[descriptionAtts.length] = new nameValuePair(fAttObj.label, aElVal);
                  }
                  else if (fAttObj.id == "Direction" && vesselDirection)
                  {
                     descriptionAtts[descriptionAtts.length] = new nameValuePair(fAttObj.label, vesselDirection);
                  }
               }
               var descrStr = getVesselDescription(descriptionAtts);

               if (vesselId == "") vesselId = vesselName;
               var vesselInfo = vesselInfoMap.get(vesselId);
               var vesselLabel = (vesselInfo && vesselInfo.label && vesselInfo.label.length > 0) ? vesselInfo.label : vesselName;
               var vesselTitle = vesselLabel;
               if (isInactive)
               {
                  vesselTitle = vesselTitle + "&nbsp;(" + INACTIVE_LABEL + ")";
               }
               else if (vesselDirection != null)
               {
                  vesselTitle = vesselTitle + "&nbsp;(" + vesselDirection + ")";
               }
               var marker = createVesselMarker(new GLatLng(vesselLat, vesselLong), vesselId, vesselLabel, vesselTitle, vesselDest, descrStr);

               // add a line to the sidebar html
               //                  sidebar_html += '<a href="javascript:vesselSelected(' + "'" + marker.id + "'" + ')">' + vesselTitle + '</a><br>';
               var sortIdx = (vesselInfo && vesselInfo.sortIdx) ? vesselInfo.sortIdx : i;
               sidebarArray[sortIdx] = '<a href="javascript:vesselSelected(' + "'" + marker.id + "'" + ')">' + vesselTitle + '</a><br>';
            }
            catch (err)
            {
               //                  alert(err);
            }
         }
         for (var i = 0; i < sidebarArray.length; i++)
         {
            // add a line to the sidebar html
            if (sidebarArray[i])
            {
               sidebar_html += sidebarArray[i];
            }
         }
      }
      // put the assembled sidebar_html contents into the sidebar div
      document.getElementById(sidebarElID).innerHTML = sidebar_html;

      if (selectedId)
      {
         vesselSelected(selectedId);
      }
   }

   function parseVesselInfoXML()
   {
      //      alert("parseVesselInfoXML");
      var data = vesselInfoData;
      var xmlDoc;
      if (data && data.documentElement)
      {
         xmlDoc = data;
      }
      if (data && data.length > 0 && !data.documentElement)
      {
         xmlDoc = GXml.parse(data);
      }

      if (xmlDoc && xmlDoc.documentElement)
      {
         //         alert(xmlDoc.documentElement);
         // Parse vessel information tags
         var vessels = getElements(xmlDoc.documentElement, "Ais_Target");
         for (var i = 0; i < vessels.length; i++)
         {
            try
            {
               var vesselId = getElementValue(vessels[i], "MMSI");
               var vesselName = getElementValue(vessels[i], "Ship_name")
               var vesselLabel = getElementValue(vessels[i], "Label")
               var vesselImg = getElementValue(vessels[i], "img");
               var vesselDesc = getElementValue(vessels[i], "description");

               if (vesselId == "") vesselId = vesselName;
               if (vesselLabel == "") vesselLabel = vesselName;

               var vesselInfo = new VesselInfo();
               vesselInfo.sortIdx = i;
               vesselInfo.id = vesselId;
               vesselInfo.name = vesselName;
               vesselInfo.label = vesselLabel;
               vesselInfo.img = vesselImg;
               vesselInfo.description = vesselDesc;

               // Get Image Info
               // South icon
               var vesselIconSouthImg = getElementValue(vessels[i], "iconSouth");
               var vesselIconSouthRef = getElementRef(vessels[i], "iconSouth");
               var viSize = vesselIconSouthRef.getAttribute("size");
               var viAnchor = vesselIconSouthRef.getAttribute("anchor");
               var sizeArr = viSize.split(",");
               var anchorArr = viAnchor.split(",");

               vesselInfo.southIcon = new GIcon(baseIconSouth);
               vesselInfo.southIcon.image = vesselIconSouthImg;
               if (sizeArr && sizeArr.length > 1 && sizeArr[0] && sizeArr[1])
               {
                  vesselInfo.southIcon.iconSize = new GSize(sizeArr[0] - 0, sizeArr[1] - 0);
                  vesselInfo.southIcon.infoWindowAnchor = new GPoint(sizeArr[0]/ 2, sizeArr[1] / 2);
               }
               if (anchorArr && anchorArr.length > 1 && anchorArr[0] && anchorArr[1])
               {
                  vesselInfo.southIcon.iconAnchor = new GPoint(anchorArr[0] - 0, anchorArr[1] - 0);
               }

               // North icon
               var vesselIconNorthImg = getElementValue(vessels[i], "iconNorth");
               var vesselIconNorthRef = getElementRef(vessels[i], "iconNorth");
               viSize = vesselIconNorthRef.getAttribute("size");
               viAnchor = vesselIconNorthRef.getAttribute("anchor");
               sizeArr = viSize.split(",");
               anchorArr = viAnchor.split(",");

               vesselInfo.northIcon = new GIcon(baseIconNorth);
               vesselInfo.northIcon.image = vesselIconNorthImg;
               if (sizeArr && sizeArr.length > 1 && sizeArr[0] && sizeArr[1])
               {
                  vesselInfo.northIcon.iconSize = new GSize(sizeArr[0] - 0, sizeArr[1] - 0);
                  vesselInfo.northIcon.infoWindowAnchor = new GPoint(sizeArr[0]/ 2, sizeArr[1] / 2);

               }
               if (anchorArr && anchorArr.length > 1 && anchorArr[0] && anchorArr[1])
               {
                  vesselInfo.northIcon.iconAnchor = new GPoint(anchorArr[0] - 0, anchorArr[1] - 0);
               }

               vesselInfoMap.put(vesselId, vesselInfo);
            }
            catch (err)
            {
               //                  alert(err);
            }
         }

         // Parse feature attributes tags
         try
         {
            //               alert("parseVesselInfoXML: Feature_attributes");
            var featureAtts = getElements(xmlDoc.documentElement, "Feature_attributes");
            if (featureAtts && featureAtts.length > 0)
            {
               var atts = getElements(featureAtts[0], "attribute");
               for (var j = 0; j < atts.length; j++)
               {
                  var fAttObj = new FeatureAttribute();
                  fAttObj.id = atts[j].getAttribute("id");
                  fAttObj.label = atts[j].getAttribute("label");
                  featureAttributes.put(fAttObj.id, fAttObj);
               }
            }
         }
         catch (err)
         {
         }

         // Parse text tags
         try
         {
            //               alert("parseVesselInfoXML: Text");
            var textValues = getElements(xmlDoc.documentElement, "Text");
            if (textValues)
            {
               for (var k = 0; k < textValues.length; k++)
               {
                  var valId = textValues[k].getAttribute("id");
                  var valLabel = textValues[k].getAttribute("label");
                  if (valId == "south") SOUTH_LABEL = valLabel;
                  if (valId == "north") NORTH_LABEL = valLabel;
                  if (valId == "inactive") INACTIVE_LABEL = valLabel;
                  textAttributes.put(valId, valLabel);
               }
               setTextAttributes();
            }
         }
         catch (err)
         {
         }
      }
      vesselInfoDone = true;
   }

   function removeVesselMarkers()
   {
      var markers = vesselMarkerMap.getValues()
      if (markers && markers.length > 0)
      {
         for (var i = 0; i < markers.length; i++)
         {
            try
            {
               map.removeOverlay(markers[i]);
            }
            catch(err)
            {
            }
         }
      }
   }

   function toBergen(dest)
   {
      if (!dest || dest.length == 0) return false;
      var lowerDest = dest.toLowerCase();
      if (lowerDest.indexOf("bgo") != -1) return true;
      if (lowerDest.indexOf("bergen") != -1) return true;
      return false;
   }

   function getElements(docEl, tagName)
   {
      if (!docEl || !tagName) return "";
      var tagEl = docEl.getElementsByTagName(tagName);
      if (!tagEl || tagEl.length == 0)
      {
         tagEl = docEl.getElementsByTagName(tagName.toLowerCase());
      }
      if (!tagEl || tagEl.length == 0)
      {
         tagEl = docEl.getElementsByTagName(tagName.toUpperCase());
      }
      return tagEl;
   }

   function getElementValue(docEl, tagName)
   {
      if (!docEl || !tagName) return "";
      var tagEl = getElements(docEl, tagName);
      var tagValue = "";
      if (tagEl && tagEl.length > 0)
      {
         var children = tagEl[0].childNodes;
         for (var i = 0; i < children.length; i++)
         {
            tagValue += children[i].nodeValue;
         }
      }
      return tagValue;
   }

   function getElementRef(docEl, tagName)
   {
      if (!docEl || !tagName) return "";
      var tagEl = getElements(docEl, tagName);
      var tagRef = null;
      if (tagEl && tagEl.length > 0)
      {
         tagRef = tagEl[0];
      }
      return tagRef;
   }

   function getLayerWidth(layer)
   {
      if (!layer) return;
      var divw = layer.offsetWidth ? layer.offsetWidth : layer.innerWidth ? layer.innerWidth : layer.firstChild ? layer.firstChild.offsetWidth ? layer.firstChild.offsetWidth : 0 : 0;
      return divw;
   }

   function getLayerHeight(layer)
   {
      if (!layer) return;
      var divh = layer.offsetHeight ? layer.offsetHeight : layer.innerHeight ? layer.innerHeight : layer.firstChild ? layer.firstChild.offsetHeight ? layer.firstChild.offsetHeight : 0 : 0;
      return divh;
   }

   function parseWMSFormattedDate(dateStr)
   {
      // eksempel på wms format:
      // 2004-06-18T12:43:06.245
      if (!dateStr || dateStr == "") return null;
      var parts = dateStr.split("T");
      if (!parts || parts.length < 2) return null;

      var datePart = parts[0];
      var ymd = datePart.split("-");
      var timePart = parts[1];
      var hms = timePart.split(":");

      var tmpDate = new Date();

      tmpDate.setUTCFullYear(ymd[0] / 1);
      tmpDate.setUTCMonth(ymd[1] / 1 - 1);
      tmpDate.setUTCDate(ymd[2] / 1);
      tmpDate.setUTCHours(hms[0] / 1);
      tmpDate.setUTCMinutes(hms[1] / 1);
      // Rounded up because wms request gives less than or equal
      tmpDate.setUTCSeconds(Math.ceil(hms[2] / 1));


      return tmpDate.getTime();
   }

   function getDateTimeString(millies)
   {
      var dateTime = new Date(millies);
      tmpStr = "";
      var s = dateTime.getDate();
      tmpStr += (s < 10 ? "0" + s : s) + ".";
      s = dateTime.getMonth() + 1;
      // jan == 0, dec == 11
      tmpStr += (s < 10 ? "0" + s : s) + ".";
      s = dateTime.getFullYear();
      tmpStr += (s < 10 ? "0" + s : s) + " ";
      s = dateTime.getHours();
      tmpStr += (s < 10 ? "0" + s : s) + ":";
      s = dateTime.getMinutes();
      tmpStr += (s < 10 ? "0" + s : s);
      return tmpStr;
   }

}
else
{
   alert("Sorry, the Google Maps API is not compatible with this browser");
}

function VesselInfo()
{
   this.id;
   this.name;
   this.label;
   this.html;
   this.img;
   this.description;
   this.southIcon;
   this.northIcon;
   this.sortIdx;
}

function FeatureAttribute()
{
   this.id;
   this.label;
   this.values;
}

function HashMap()
{
   this.list = new Array();
   this.keys = new Array();
   this.values = new Array();

   this.init = function()
   {
      this.list = new Array();
      this.keys = new Array();
      this.values = new Array();
   }

   this.get = function(id)
   {
      for (var i = 0; i < this.list.length; i++)
      {
         var param = this.list[i];
         if (param.id == id)
         {
            return param.value;
         }
      }
      return null;
   }

   this.getIgnoreCase = function(id)
   {
      var upperName = id.toUpperCase();
      for (var i = 0; i < this.list.length; i++)
      {
         var param = this.list[i];
         var upperParamName = param.id.toUpperCase();
         if (upperParamName == upperName)
         {
            return param.value;
         }
      }
      return null;
   }

   this.getIndex = function(id)
   {
      for (var i = 0; i < this.list.length; i++)
      {
         var param = this.list[i];
         if (param.id == id)
         {
            return i;
         }
      }
      return -1;
   }

   this.put = function(id, value)
   {
      var idx = this.getIndex(id);
      if (idx == -1) idx = this.list.length;

      this.list[idx] = new nameValuePair(id, value);
      this.keys[idx] = id;
      this.values[idx] = value;
   }

   this.remove = function(id)
   {
      var idx = this.getIndex(id);
      if (idx == -1) return false;

      var tmpList = this.list;
      this.init();
      for (var i = 0; i < tmpList.length; i++)
      {
         if (i != idx)
         {
            this.put(tmpList[i].id, tmpList[i].value);
         }
      }
   }

   this.addValue = function(id, value, ignoreCase)
   {
      var oldValue = ignoreCase ? this.getIgnoreCase(id) : this.get(id);
      var newValue = (oldValue && oldValue != "") ? oldValue + "," + value : value;
      this.put(id, newValue);
   }

   this.getKeys = function()
   {
      return this.keys;
   }

   this.getValues = function()
   {
      return this.values;
   }

   this.length = function()
   {
      return this.list.length;
   }

   this.makeQueryString = function(keyStr)
   {
      if (!this.list || this.list.length == 0) return "";
      var keyArr = null;
      if (keyStr && keyStr.length > 0)
      {
         keyArr = keyStr.split(",");
      }

      var qStr = "";
      for (var i = 0; i < this.list.length; i++)
      {
         if (keyArr == null || !arrayContaines(keyArr, this.list[i].id))
         {
            qStr += "&" + this.list[i].id + "=";
            qStr += this.list[i].value;
         }
      }
      return qStr;
   }

}

function nameValuePair(id, value)
{
   this.id = id;
   this.value = value;
}

function getXMLHttpRequest()
{
   try
   {
      if (window.XMLHttpRequest)
      {
         // ikke IE browser
         return new XMLHttpRequest();
      }
      else if (window.ActiveXObject)
      {
         // branch for IE/Windows ActiveX version
         var ua = navigator.userAgent.toLowerCase();
         if (ua.indexOf('msie 5') == -1)
            return new ActiveXObject("Msxml2.XMLHTTP");
         else
            return new ActiveXObject("Microsoft.XMLHTTP");
      }
   }
   catch(err)
   {
      return null;
   }
}

function requestObject()
{
   var obRef = this;
   this.req = null;
   this.callbackFunction = null;
   this.xml = false;

   this.downloadXML = function(url, callbackFunction)
   {
      this.xml = true;
      this.sendXMLHttpRequest(url, callbackFunction);
   }

   this.sendXMLHttpRequest = function(url, callbackFunction)
   {
      try
      {
         this.req = getXMLHttpRequest();
         if (this.req == null)
         {
            alert("Unable to create XMLHttpRequest");
            return;
         }
         this.callbackFunction = callbackFunction;
         if (callbackFunction)
         {
            this.req.onreadystatechange = function()
            {
               obRef.reqChangeEvent();
            };
         }
         this.req.open("GET", url, true);
         this.req.send(null);
      }
      catch(err)
      {
      }
   }

   this.reqChangeEvent = function()
   {
      try
      {
         if (!this.req)
         {
            alert("There was a problem retrieving the data.");
         }
         // only if req shows "loaded"
         if (this.req.readyState == 4)
         {
            // only if "OK"
            if (this.req.status == 200)
            {
               // ...processing statements go here...
               //               alert(this.req.responseText);
               this.callbackFunction(this.xml ? this.req.responseXML : this.req.responseText, this.req.status);
               this.busy = false;
            }
            else
            {
               alert("There was a problem retrieving the data:\n" + this.req.statusText);
               this.busy = false;
            }
         }
      }
      catch(err)
      {
      }
   }

}