function DOMRemoveChilds(DOMNode)
{
    for (var Iterator = DOMNode.childNodes.length - 1 ; Iterator >= 0  ; Iterator--)
        DOMNode.removeChild(DOMNode.childNodes[Iterator]);
}

var PANNING_ALLOW = 0;
var PANNING_REPOSITION = 1;
var PANNING_DISABLE = 2;

var OFFSET_CONTROL = 10;
var DEFAULT_SELECTOR_CAPTION = '---- Maak een keuze ----';

function MapControl(MapData)
{
    this.Markers = new Array();
    this.Icons = new Array();
    this.Content = new Array();
    this.MapData = MapData;
    this.MapForm;
    
    this.Initialize = function()
    {
        if (this.MapData.AttachForm)
            this.MapForm = new MapForm(this);
    }

    this.GetIconByID_ = function(ID)
    {
        for (var Iterator = 0 ; Iterator < this.Icons.length ; Iterator++)
            if (this.Icons[Iterator].ID == ID)
                return this.Icons[Iterator];
        return null;
    }

    this.CreateIcon_ = function(IconData)
    {
        var Icon = new GIcon();
        Icon.image = IconData.Image;
        
        if (IconData.ShadowImage != null)
        {
            // TODO shadowimage
            Icon.imageShadow = IconData.ShadowImage;
        }
        
        Icon.iconSize = new GSize(IconData.Width, IconData.Height);
        Icon.iconAnchor = new GPoint(IconData.AnchorX, IconData.AnchorY)
        Icon.infoWindowAnchor = new GPoint(IconData.InfoAnchorX, IconData.InfoAnchorY);

        return Icon;
    }
    
    this.GetMarkerByID_ = function(ID)
    {
        for (var Iterator = 0 ; Iterator < this.Markers.length ; Iterator++)
            if (this.Markers[Iterator].ID == ID)
                return this.Markers[Iterator];
        return null;
    }

    this.CreateMarker_ = function(MarkerData)
    {
        var Point = new GLatLng(MarkerData.Latitude, MarkerData.Longitude);
        var Icon = this.GetIconByID_(MarkerData.IconID);

        return (Icon != null)? new GMarker(Point, {icon : Icon.Object}) : new GMarker(Point);        
    }

    this.GetMarkersBounds_ = function(ParentID)
    {
        var Bounds = new GLatLngBounds();
        for (var Iterator = 0 ; Iterator < this.Markers.length ; Iterator++)
        {
            if (this.Markers[Iterator].GroupID == ParentID)
            {
                Bounds.extend(this.Markers[Iterator].Object.getPoint());
            }
        }
        return Bounds;
    }
    
    this.MarkerHasChildren_ = function(ParentID)
    {
        for (var Iterator = 0 ; Iterator < this.Markers.length ; Iterator++)
        {
            if (this.Markers[Iterator].GroupID == ParentID)
                return true;
        }
        return false;
    }

    /** @todo Param wijzigen naar een conditions literal **/

    this.DrawMarkers_ = function(ParentID)
    {
        var MarkerCount = 0;

        this.MapData.Object.clearOverlays();

        if (this.MapData.AttachForm)
        {
            if (ParentID == 0)
                this.MapForm.Clear();

            var Selector = this.MapForm.AddSelector(ParentID);
        }

        for (var Iterator = 0 ; Iterator < this.Markers.length ; Iterator++)
        {
            if (this.Markers[Iterator].GroupID == ParentID)
            {
                this.MapData.Object.addOverlay(this.Markers[Iterator].Object);
                
                if (this.MapData.ShowCaptions)
                    this.MapData.Object.addOverlay(new MarkerTooltip(this.Markers[Iterator].Object));
                
                if (this.MapData.AttachForm)
                    Selector.AddOption(this.Markers[Iterator].Caption, this.Markers[Iterator].ID);
                
                MarkerCount++;
            }
        }
        return (MarkerCount == 0 && ParentID != 0)? this.DrawMarkers_(0) : ParentID;
    }
    
    this.getMapType_ = function(intType)
    {
        switch (intType)
        {
            case 1:
                return G_SATELLITE_MAP;

            case 2:
                return G_HYBRID_MAP;
        }
        return G_NORMAL_MAP;
    }

    this.DrawMap_ = function(Bounds, Initialize)
    {
        // Iets uitzoomen, zodat alles er goed op staat.
        var ZoomLevel = this.MapData.Object.getBoundsZoomLevel(Bounds) - 3;

        this.MapData.Center = Bounds.getCenter()

        if (Initialize)
        {
            this.MapData.Object.setCenter(this.MapData.Center, ZoomLevel);
            this.MapData.Object.setMapType(this.getMapType_(this.MapData.MapType));
            this.DrawMarkers_(0);
        }
        else
        {
            this.MapData.Object.setZoom(ZoomLevel);
            this.MapData.Object.panTo(this.MapData.Center);
        }

        if (this.MapData.AttachForm)
            this.MapData.Pane.appendChild(this.MapForm.ToString());
    }
    
    this.DefineIcon = function(IconData)
    {
        if (this.GetIconByID_(IconData.ID) == null)
        {
            IconData.Object = this.CreateIcon_(IconData);
            this.Icons.push(IconData);
        }
    }

    this.DefineMarker = function(MarkerData)
    {
        if (this.GetMarkerByID_(MarkerData.ID) == null)
        {
            MarkerData.Object = this.CreateMarker_(MarkerData);
            MarkerData.Object.Data = MarkerData;
            MarkerData.Object.MapData = this.MapData;
            MarkerData.Object.MapControl = this;
            
            MarkerData.Content = new Array();

            this.Markers.push(MarkerData);
        }
    }
    
    this.DefineMarkerContent = function(MarkerContent)
    {
        this.GetMarkerByID_(MarkerContent.MarkerID).Content.push(MarkerContent);
    }

    this.Render = function()
    {
        if (GBrowserIsCompatible())
        {
            this.MapData.Pane = document.getElementById(this.MapData.ElementID);

            if (this.MapData.LoadingImage)
            {
                this.MapData.Pane.style.backgroundImage = "";
            }

            this.MapData.Object = new GMap2(this.MapData.Pane);
            this.DrawMap_(this.GetMarkersBounds_(0), true);

            GEvent.bind(this.MapData.Object, "click", this, this.OnClick);
            
            if (this.MapData.PanningAction != PANNING_DISABLE)
                GEvent.bind(this.MapData.Object, "drag", this, this.OnDrag);
    
            // Controls
    
            if (this.MapData.PanningAction == PANNING_ALLOW && this.MapData.PanningControl >= 0)
                this.MapData.Object.addControl(new GSmallMapControl(), this.GetControlPosition(this.MapData.PanningControl));
    
            if (this.MapData.ScaleControl >= 0)
                this.MapData.Object.addControl(new GScaleControl(), this.GetControlPosition(this.MapData.ScaleControl));
    
            if (this.MapData.MapTypeControl >= 0)
                this.MapData.Object.addControl(new GMapTypeControl(), this.GetControlPosition(this.MapData.MapTypeControl));
        }
    }
    
    this.GetControlPosition = function(Numeric) 
    {
        var Anchor;
        switch (Numeric)
        {
            case 0: Anchor = G_ANCHOR_TOP_RIGHT; break;
            case 1: Anchor = G_ANCHOR_TOP_LEFT; break;
            case 2: Anchor = G_ANCHOR_BOTTOM_RIGHT; break;
            case 3: Anchor = G_ANCHOR_BOTTOM_LEFT;
        }
        return new GControlPosition(Anchor, new GSize(OFFSET_CONTROL, OFFSET_CONTROL));
    }
    
    this.ShowMarkerContent_ = function(Marker)
    {
        if (Marker.Content.length > 0)
        {
            var InfoWindowTabs = new Array();
            for (var Iterator = 0 ; Iterator < Marker.Content.length ; Iterator++)
            {
                InfoWindowTabs.push(new GInfoWindowTab(
                    Marker.Content[Iterator].Caption,
                    Marker.Content[Iterator].Content
                ));
            }
            Marker.Object.openInfoWindowTabsHtml(InfoWindowTabs, {maxWidth : 200});
        }
        else
        {
            //var LocationInfo = Marker.Location.split(', ');
            
            //this.MapData.Object.addOverlay(new MarkerTooltip(Marker.Object));
            var contents = document.createElement("div");
            contents.innerHTML = Marker.Caption;
            Marker.Object.openInfoWindow(contents);
        }
    }
    
    // Redraw de map aan de hand van een opgegeven bovenliggend punt (ParentID)
    this.Redraw = function(ParentID)
    {
        (this.MarkerHasChildren_(ParentID))?
            this.DrawMap_(this.GetMarkersBounds_(this.DrawMarkers_(ParentID))) :
            this.ShowMarkerContent_(this.GetMarkerByID_(ParentID));
    }

    this.OnDrag = function()
    {
        if (!this.MapData.Object.getBounds().contains(this.MapData.Center) && this.MapData.PanningAction == PANNING_REPOSITION)
            this.MapData.Object.panTo(this.MapData.Center);
    }
    
    this.OnClick = function(Overlay, Point)
    {
        if (Overlay != null)
        {
            if (this.MapData.AttachForm)
                this.MapForm.SelectOption(Overlay.Data.GroupID, Overlay.Data.ID);
            
            this.Redraw(Overlay.Data.ID);
        }
        //else
        //    logMessage("Klik op punt: " + Point);
    }
}

function MapForm(MapControl)
{
    this.MapControl_ = MapControl;
    this.Selectors_ = new Array();
    this.Element_ = null;

    this.Draw_ = function()
    {
        this.Element_ = document.createElement("div");
        this.Element_.className = "MapForm";
    }

    this.SelectOption = function(GroupID, ID)
    {
        for (var Iterator = 0 ; Iterator < this.Selectors_.length  ; Iterator++)
        {
            if (this.Selectors_[Iterator].ParentID == GroupID)
                this.Selectors_[Iterator].SelectOption(ID);
        }
    }

    this.AddSelector = function(ParentID)
    {
        var Selector = new MapFormSelector(this.MapControl_, this);
        Selector.ParentID = ParentID;
        Selector.AddOption(DEFAULT_SELECTOR_CAPTION, ParentID);
        
        this.Selectors_.push(Selector);
        return Selector;
    }
    
    this.ToString = function()
    {
        if (this.Element_ == null)
            this.Draw_();

        for (var Iterator = 0 ; Iterator < this.Selectors_.length ; Iterator++)
            this.Element_.appendChild(this.Selectors_[Iterator].ToString());

        return this.Element_;
    }

    this.Clear = function(ParentID)
    {
        var IsLast;
        if (this.Element_ != null)
        {
            if (this.Element_.parentNode != null)
                this.Element_.parentNode.removeChild(this.Element_);
    
            for (var Iterator = this.Selectors_.length - 1 ; Iterator >= 0 ; Iterator--)
            {
                IsLast = ParentID && this.Selectors_[Iterator].ParentID == ParentID;
                
                this.Selectors_[Iterator].Clear();
                this.Selectors_.pop();
                
                if (IsLast) break;
            }
            DOMRemoveChilds(this.Element_);
        }
    }
}

function MapFormSelector(MapControl, MapForm)
{
    this.ParentID;

    this.Options_ = new Array();
    this.MapControl_ = MapControl;
    this.MapForm_ = MapForm;
    this.Element_ = null;
    this.SelectedOption = null;

    this.Draw_ = function()
    {
        this.Element_ = document.createElement("select");
        this.Element_.Data = this;
        this.Element_.MapControl = this.MapControl_;
        this.Element_.MapForm = this.MapForm_;
        this.AttachListener_();

        for (var Iterator = 0 ; Iterator < this.Options_.length ; Iterator++)
            this.Element_.appendChild(this.Options_[Iterator].ToString());
    }

    this.AttachListener_ = function()
    {
        (browser.isIE())?
            this.Element_.attachEvent("onchange", this.OnSelection) : 
            this.Element_.addEventListener("change", this.OnSelection, false);
    }

    this.AddOption = function(Caption, ParentID) 
    {
        var Option = new MapFormSelectorOption();
        Option.Caption = Caption;
        Option.ParentID = ParentID;
        
        this.Options_.push(Option);
        return Option;
    }
    
    this.SelectOption = function(ParentID)
    {
        for (var Iterator = 0 ; Iterator < this.Element_.options.length ; Iterator++)
        {
            if (this.Element_.options[Iterator].Data.ParentID == ParentID)
                this.Element_.options[Iterator].selected = "selected";
        }
    }

    this.OnSelection = function()
    {
        var Selector = (browser.isIE())?
            window.event.srcElement : this;

        // Andere option, re-evaluate/draw onderliggende selectors
        if (Selector.Data.SelectedParentID != null)
            Selector.MapForm.Clear(Selector.Data.SelectedParentID)

        Selector.Data.SelectedParentID = Selector.options[Selector.selectedIndex].ParentID;
        Selector.MapControl.Redraw(Selector.Data.SelectedParentID);
    }
    
    this.ToString = function()
    {
        if (this.Element_ == null)
            this.Draw_();

        return this.Element_; 
    }
    
    this.Clear = function()
    {
        for (var Iterator = this.Options_.length - 1 ; Iterator >= 0  ; Iterator--)
        {
            this.Options_[Iterator].Clear();
            this.Options_.pop();
        }
        this.Element_ = null;
    }
}

function MapFormSelectorOption()
{
    this.Caption;
    this.ParentID;

    this.Element_ = null;

    this.Draw_ = function()
    {
        this.Element_ = document.createElement("option");
        this.Element_.Data = this;
        this.Element_.appendChild(document.createTextNode(this.Caption));
        this.Element_.ParentID = this.ParentID;
    }

    this.ToString = function()
    {
        if (this.Element_ == null)
            this.Draw_();

        return this.Element_; 
    }
    
    this.Clear = function()
    {
        this.Element_ = null;
    }
}

function MarkerTooltip(GMarker)
{
    this.GMarker_ = GMarker;

    this.initialize = function(Map)
    {
        var Div = document.createElement("div");
        Div.style.border = "1px solid #000";
        Div.style.position = "absolute";
        Div.style.backgroundColor = "#FFF";
        Div.style.padding = "2px 5px";
        Div.style.textAlign = "center";
        Div.style.width = "80px";
        Div.style.fontSize = "10px";
        //Div.style.cursor = "Pointer";
        Div.appendChild(document.createTextNode(this.GMarker_.Data.Caption));

        Map.getPane(G_MAP_MAP_PANE).appendChild(Div);
        
        this.Map_ = Map;
        this.Div_ = Div;
    }
    
    this.remove = function()
    {
        this.Div_.parentNode.removeChild(this.Div_);
    }
    
    this.copy = function()
    {
        return new MapTooltip(this._GMarker);
    }
    
    this.redraw = function(Force)
    {
        if (!Force)
            return;

        var GIcon = this.GMarker_.getIcon();

        var Position = this.Map_.fromLatLngToDivPixel(this.GMarker_.getPoint());
        var IconSize = GIcon.iconSize;
        var Anchor = GIcon.infoWindowAnchor;

        this.Div_.style.left = (Position.x - IconSize.width - Anchor.x) + "px";
        this.Div_.style.top = (Position.y - IconSize.height - 15 - Anchor.y) + "px"; 
    }
    
    this.prototype = new GOverlay();
}

function MapLoader()
{
    this.LoadStack = new Array();
    this.UnloadStack = new Array();

    this.Initialize = function()
    {
        this.HookStack("load");
        this.HookStack("unload");
    }
    
    this.HookStack = function(Event)
    {
        (browser.isIE())?
            window.attachEvent("on" + Event, this.ProcessStack) : 
            window.addEventListener(Event, this.ProcessStack, false);
    }
    
    this.ProcessStack = function(Event)
    {
        var Stack = MapLoader[Event.type.substr(0, 1).toUpperCase() + Event.type.substr(1) + "Stack"];

        for (var Iterator = 0 ; Iterator < Stack.length ; Iterator++)
            Stack[Iterator]();
    }
}

var MapLoader = new MapLoader();
MapLoader.Initialize();