﻿//General Map
GeneralMap = {
    SatLblUrl : "",
    MapType : { VietbandoMap : 0, GoogleMap : 1},
    LatLng : function(latitude, longitude, unbounded)
    {
        if (GeneralMap.mapType == GeneralMap.MapType.VietbandoMap)
            return new VLatLng(latitude, longitude, unbounded);
        else
            return new GLatLng(latitude, longitude, unbounded);
    },
    Size : function(width, height)
    {
        if (GeneralMap.mapType == GeneralMap.MapType.VietbandoMap)
            return new VSize(width, height);
        else
            return new GSize(width, height);
    },
    Control : function()
    {
        if (GeneralMap.mapType == GeneralMap.MapType.VietbandoMap)
            return new VControl();
        else
            return new GControl();
    },
    ControlPosition : function(anchor, offset)
    {
        if (GeneralMap.mapType == GeneralMap.MapType.VietbandoMap)
            return new VControlPosition(anchor, offset);
        else
            return new GControlPosition(anchor, offset);
    },
    LatLngBounds : function(nw, se)
    {
        if (GeneralMap.mapType == GeneralMap.MapType.VietbandoMap)
        {
            return new VLatLngBounds(nw, se);
        }
        else
        {
            var ne = new GLatLng(nw.y, se.x);
            var sw = new GLatLng(se.y, nw.x);
            return new GLatLngBounds(sw, ne);
        }
    },
    InfoWindowOptions : function(offset, selectedTab, maxWidth, onOpenFn, onCloseFn, zoomLevel, maxContent, maxTitle, autoPan, mapBlowup, maximizeWhenOpen)
    {
        if (GeneralMap.mapType == GeneralMap.MapType.VietbandoMap)
            return new VInfoWindowOptions(offset, selectedTab, maxWidth, onOpenFn, onCloseFn, zoomLevel, maxContent, maxTitle, autoPan, mapBlowup, maximizeWhenOpen);
        else
            return { pixelOffset : offset, selectedTab : selectedTab, maxWidth : maxWidth, onOpenFn : onOpenFn, onCloseFn : onCloseFn, zoomLevel : zoomLevel, maxContent : maxContent, maxTitle : maxTitle };
    },
    InfoWindowTab : function(label, content)
    {
        if (GeneralMap.mapType == GeneralMap.MapType.VietbandoMap)
            return new VInfoWindowTab(label, content);
        else
            return new GInfoWindowTab(label, content);
    },
    MapOptions : function(size, draggableCursor, draggingCursor)
    {
        if (GeneralMap.mapType == GeneralMap.MapType.VietbandoMap)
            return new VMapOptions();
        else
            return { size : size, draggableCursor : draggableCursor, draggingCursor : draggingCursor };
    },
    MarkerOptions : function(icon, zIndexProcess, offset, alongText, textPosition, textStyle, title, clickable, draggable, autoPan)
    {
        if (GeneralMap.mapType == GeneralMap.MapType.VietbandoMap)
        {
            return new VMarkerOptions(icon, alongText, textPosition, textStyle, title, clickable, draggable, offset, autoPan, zIndexProcess);
        }
        else
        {
            if (offset != undefined)
                icon.iconAnchor = new GPoint(offset.width, offset.height);
            return { icon : icon, title : title, clickable : clickable, draggable : draggable, autoPan : autoPan, zIndexProcess : zIndexProcess, bouncy : false };
        }
    },
    PolygonOptions : function()
    {
        if (GeneralMap.mapType == GeneralMap.MapType.VietbandoMap)
            return new VPolygonOptions(clickable);
        else
            return { clickable : clickable };
    },
    TextPosition : function(anchor, offset)
    {
        if (GeneralMap.mapType == GeneralMap.MapType.VietbandoMap)
            return new VTextPosition(anchor, offset);
        else
            return null;
    },
    TextStyle : function(fontSize, fontWeight, color, fontFamily)
    {
        return new VTextStyle(fontSize, fontWeight, color, fontFamily);
    },
    PolylineOptions : function(clickable, geodesic, dashStyle)
    {
        if (GeneralMap.mapType == GeneralMap.MapType.VietbandoMap)
            return new VPolylineOptions(clickable, geodesic, dashStyle);
        else
            return { clickable : clickable, geodesic : geodesic };
    },
    CircleOptions : function(clickable, geodesic, dashStyle)
    {
        if (GeneralMap.mapType == GeneralMap.MapType.VietbandoMap)
            return new VCircleOptions(clickable, geodesic, dashStyle);
        else
            return null;
    },
    Util : {
        CreateDivElement : function(id, left, top, width, height, position, overflow, inner)
        {
            return VUtil.CreateDivElement(id, left, top, width, height, position, overflow, inner);
        },
        Distance : function(x1, y1, x2, y2)
        {
            return VUtil.Distance(x1, y1, x2, y2);
        },
        ProjectPoint : function (x, y, x1, y1, x2, y2)
        {
	        if ((x == x1 && y == y1) || (x == x2 && y == y2))
		        return new GeneralMap.LatLng(y, x);
	        var r = VUtil.ProjectFactor(x, y, x1, y1, x2, y2);
	        return new GeneralMap.LatLng(y1+r*(y2-y1), x1+r*(x2-x1));
        },
        ClosestPoint : function (x, y, x1, y1, x2, y2)
        {
	        var d1, d2, f = VUtil.ProjectFactor(x, y, x1, y1, x2, y2);
	        if (f > 0 && f < 1)
		        return GeneralMap.Util.ProjectPoint(x, y, x1, y1, x2, y2);
	        d1 = GeneralMap.Util.Distance(x, y, x1, y1);
	        d2 = GeneralMap.Util.Distance(x, y, x2, y2);
	        if (d1 < d2)
		        return GeneralMap.LatLng(y1, x1);
	        return GeneralMap.LatLng(y2, x2);
        },
        ClosestPointPolyline : function (x, y, arrP, arrRet)
        {
            var eIndex = 0;
	        var x1, y1, x2, y2;
        	
	        var cp = new GeneralMap.LatLng(0, 0);
	        var	sp = new GeneralMap.LatLng(0, 0);
	        var cpDist, spDist;
	        var i, N = arrP.length;
        	
	        x1 = arrP[0].lng();
	        y1 = arrP[0].lat();
	        x2 = arrP[1].lng();
	        y2 = arrP[1].lat();
	        sp = GeneralMap.Util.ClosestPoint(x, y, x1, y1, x2, y2);
	        spDist = GeneralMap.Util.Distance(x, y, sp.lng(), sp.lat());

	        for (i = 1; i < N - 1; i++)
	        {
		        x1 = arrP[i].lng();
		        y1 = arrP[i].lat();
		        x2 = arrP[i+1].lng();
		        y2 = arrP[i+1].lat();
		        cp = this.ClosestPoint(x, y, x1, y1, x2, y2);
		        cpDist = this.Distance(x, y, cp.lng(), cp.lat());
		        if (cpDist < spDist)
		        {
			        spDist = cpDist;
			        sp = cp;
			        eIndex = i;
		        }
	        }
	        arrRet[0] = sp;
	        arrRet[1] = eIndex;
        },
        ClosestPointPolylines : function (x, y, arrPs, arrRet)
        {
            var minDis = null;
            var eIndex = 0;
            var eCount = 0;
            var	sp = new GeneralMap.LatLng(0, 0);
            for (var i = 0; i < arrPs.length; i++)
            {
                var arrPi = arrPs[i];
	            var arrReti = new Array();
	            GeneralMap.Util.ClosestPointPolyline(x, y, arrPi, arrReti);
	            if (minDis == null)
	            {
	                minDis = GeneralMap.Util.Distance(x, y, arrReti[0].x, arrReti[0].y);
	                sp = arrReti[0];
	            }
	            else
	            {
	                var dis = GeneralMap.Util.Distance(x, y, arrReti[0].x, arrReti[0].y);
	                if (minDis > dis)
	                {
	                    minDis = dis;
	                    sp = arrReti[0];
	                    eIndex = eCount + arrReti[1];
	                }
	            }
	            eCount += arrPs[i].length;
            }
            arrRet[0] = sp;
	        arrRet[1] = eIndex;
        },
        isInsidePolygon : function(pt, arrPts)
        {
            if (GeneralMap.mapType == GeneralMap.MapType.VietbandoMap)
            {
                return VUtil.isInsidePolygon(pt, arrPts);
            }
            else
            {
                var bInside = false;
	            var i;
	            var nPt = arrPts.length;
	            for (i = 0; i < nPt-1; i++)
	            {
		            if ((((arrPts[i+1].lat() <= pt.lat()) && (pt.lat() < arrPts[i].lat())) ||
			            ((arrPts[i].lat() <= pt.lat()) && (pt.lat() < arrPts[i+1].lat()))) &&
			            (pt.lng() < (arrPts[i].lng() - arrPts[i+1].lng())*(pt.lat() - arrPts[i+1].lat()) /
			            (arrPts[i].lat() - arrPts[i+1].lat()) + arrPts[i+1].lng()))
			            bInside = !bInside;
	            }
	            return bInside;
            }
        },
        getCenterPoint : function(arrPts)
        {
            if (GeneralMap.mapType == GeneralMap.MapType.VietbandoMap)
            {
                return VUtil.getCenterPoint(arrPts);
            }
            else
            {
                var nPt = arrPts.length;
	            var fArea = 0;
	            var v;
	            for (v = 0; v < nPt-1; v++)
		            fArea += (arrPts[v].lat() + arrPts[v+1].lat()) * (arrPts[v].lng() - arrPts[v+1].lng());
	            fArea *= 3;
	            var xc = 0;
	            var yc = 0;
	            for (v = 0; v < nPt-1; v++)
	            {
		            xc += (arrPts[v].lng() + arrPts[v+1].lng()) * (arrPts[v].lng() * arrPts[v+1].lat() - arrPts[v+1].lng() * arrPts[v].lat());
		            yc += (arrPts[v].lat() + arrPts[v+1].lat()) * (arrPts[v].lng() * arrPts[v+1].lat() - arrPts[v+1].lng() * arrPts[v].lat());
	            }
	            xc = xc/fArea;
	            yc = yc/fArea;
	            return new GLatLng(yc, xc);
	        }
        }
    },
    Overlay : function()
    {
        if (GeneralMap.mapType == GeneralMap.MapType.VietbandoMap)
            return new VOverlay();
        else
            return new GOverlay();
    },
    Event : {
        addListener : function(source, vEvent, handler)
        {
            var rSource = null;
            if (source.vType != undefined && typeof source.vType == 'function' && source.vType() == "GeneralMap")
                rSource = source.mapObj;
            else
                rSource = source;
            
            if (GeneralMap.mapType == GeneralMap.MapType.VietbandoMap)
            {
                return VEvent.addListener(rSource, vEvent, handler);
            }
            else
            {
                if (source.vType != undefined && typeof source.vType == 'function' && (source.vType() == "VPolyline" || source.vType() == "VPolygon"))
                {
                    source.vEvent = vEvent;
                    source.handler = handler;
                    source.addLineHandlers(vEvent, handler);
                }
                else
                {
                    if (vEvent == 'moving')
                        vEvent = 'move';
                    else if (vEvent == 'dragging')
                        vEvent = 'drag';
                    else if (vEvent == 'infowindowclosebuttonclick')
                        vEvent = 'closeclick';
                    return GEvent.addListener(rSource, vEvent, handler);
                }
            }
        },
        addDOMListener : function(source, vEvent, handler)
        {
            if (GeneralMap.mapType == GeneralMap.MapType.VietbandoMap)
                return VEvent.addDOMListener(source, vEvent, handler);
            else
                return GEvent.addDomListener(source, vEvent, handler);
        },
        removeListener : function(handle)
        {
            if (GeneralMap.mapType == GeneralMap.MapType.VietbandoMap)
                return VEvent.removeListener(handle);
            else
                return GEvent.removeListener(handle);
        }
    },
    Icon : function(icon, iconSize)
    {
        if (GeneralMap.mapType == GeneralMap.MapType.VietbandoMap)
        {
            return new VIcon(icon, iconSize);
        }
        else
        {
            var gi = new GIcon(G_DEFAULT_ICON);
            gi.image = icon;
            gi.iconSize = iconSize;
            gi.shadow = "";
            gi.shadowSize = new GSize(0, 0);
            gi.dragCrossImage = 'empty.gif';
            gi.dragCrossSize = GSize(0, 0);
            gi.maxHeight = 0;
            return gi;
        }
    },
    LargeMapControl : function()
    {
        if (GeneralMap.mapType == GeneralMap.MapType.VietbandoMap)
            return new VLargeMapControl();
        else
            return new GLargeMapControl3D();
    },
    SmallMapControl : function()
    {
        if (GeneralMap.mapType == GeneralMap.MapType.VietbandoMap)
            return new VSmallMapControl();
        else
            return new GSmallMapControl();
    },
    SmallZoomControl : function()
    {
        if (GeneralMap.mapType == GeneralMap.MapType.VietbandoMap)
            return new VSmallZoomControl();
        else
            return new GSmallZoomControl3D();
    },
    ScaleControl : function()
    {
        if (GeneralMap.mapType == GeneralMap.MapType.VietbandoMap)
            return new VScaleControl();
        else
            return new GScaleControl();
    },
    OverviewMapControl : function()
    {
        if (GeneralMap.mapType == GeneralMap.MapType.VietbandoMap)
            return new VOverviewMapControl();
        else
            return new GOverviewMapControl(new GSize(145, 125));
    },
    mapType : 0,
    Map : function(container)
    {
        this.mapContainer = container;
        this.prevWidth = container.offsetWidth;
        this.prevHeight = container.offsetHeight;
        if (GeneralMap.mapType == GeneralMap.MapType.VietbandoMap)
        {
            this.mapObj = new VMap(container);
            var key = new VKeyboardHandler(this.mapObj);
        }
        else
        {
            GLatLngBounds.prototype.getNorthWest = function()
            {
                var sw = this.getSouthWest();
                var ne = this.getNorthEast();
                var nw = new GLatLng(ne.y, sw.x);
                return nw;
            }
            
            GLatLngBounds.prototype.getSouthEast = function()
            {
                var sw = this.getSouthWest();
                var ne = this.getNorthEast();
                var se = new GLatLng(sw.y, ne.x);
                return se;
            }
            
            GLatLng.prototype.vType = function(){
                    return "VLatLng";
                };
            
            GOverlay.prototype.vType = function(){
                    return "VOverlay";
                };
            
            GMarker.prototype.vType = function(){
                    return "VMarker";
                };
            
            /*GPolyline.prototype.vType = function(){
                    return "GPolyline";
                };
            
            GPolygon.prototype.vType = function(){
                    return "VPolygon";
                };*/
                
            GLargeMapControl.prototype.vType = function(){
                    return "VLargeMapControl";
                };
            
            GSmallMapControl.prototype.vType = function(){
                    return "VSmallMapControl";
                };
            
            GSmallZoomControl.prototype.vType = function(){
                    return "VSmallZoomControl";
                };
            
            GScaleControl.prototype.vType = function(){
                    return "VScaleControl";
                };
            
            GOverviewMapControl.prototype.vType = function(){
                    return "VOverviewMapControl";
                };
                
            GIcon.prototype.vType = function(){
                    return "VIcon";
                };
            
            this.mapObj = new GMap2(container, {backgroundColor : "#ffffff"});
            var key = new GKeyboardHandler(this.mapObj);
            
            var tilelayers = new GTileLayer(new GCopyrightCollection("Vietbando Inc"), 5, 18);
        
            tilelayers.getCopyright = function(a, b)
            {
                return {prefix: "© 2009", copyrightTexts:["Vietbando Inc"]};
            }
            
            tilelayers.isPng = function()
            {
                return true;
            }
            
            tilelayers.getOpacity = function()
            {
                return 1;
            }
            
            tilelayers.getTileUrl = function(point, zoom)
            {
                if (zoom < 5 || zoom > 18)
                    return "";
                var tf = parseInt((point.y * Math.pow(2, zoom) + point.x) / LimitFolder);
                return GeneralMap.SatLblUrl + zoom + "/" + tf + "/" + point.y + "_" + point.x + ".png";
            };
            
            var hybridLayer = null;
            if (GeneralMap.SatLblUrl != "")
                hybridLayer = [ G_SATELLITE_MAP.getTileLayers()[0], tilelayers ];
            else
                hybridLayer = [ G_SATELLITE_MAP.getTileLayers()[0], G_HYBRID_MAP.getTileLayers()[1] ];
            hybrid = new GMapType(hybridLayer, G_SATELLITE_MAP.getProjection(), "SATELLITE", {maxResolution : 18, minResolution : 5, errorMessage : "No Data Available"}) ;
            this.mapObj.addMapType(hybrid);
            
            this.mapObj.setCenter(new GLatLng(14.102779, 109.649509), 5, hybrid);
            
            this.mapObj.enableScrollWheelZoom();
            this.mapObj.enableContinuousZoom();
            this.arrControls = new Array();
            this.nControls = 0;
            this.arrOverlays = new Array();
            this.nOverlays = 0;
            
            this.mapObj.getInfoWindow().updateMaxTitle = function(strMaxTitle){
                    try
                    {
                        infoWindow.getContentContainers()[0].childNodes[0].childNodes[0].childNodes[0].innerHTML = strMaxTitle;
                    }
                    catch (exp)
                    {   
                    }
                };
            
            this.mapObj.getInfoWindow().updateMaxContent = function(strMaxContent){
                    try
                    {
                        infoWindow.getContentContainers()[0].childNodes[0].childNodes[1].innerHTML = strMaxContent;
                    }
                    catch (exp)
                    {
                    }
                };
        }
        
        this.hideControls = hideControls;
	    this.showControls = showControls;
        this.enableDragging = enableDragging;
	    this.disableDragging = disableDragging;
	    this.draggingEnabled = draggingEnabled;
	    this.enableInfoWindow = enableInfoWindow;
	    this.disableInfoWindow = disableInfoWindow;
	    this.infoWindowEnabled = infoWindowEnabled;
	    this.enableDoubleClickZoom = enableDoubleClickZoom;
	    this.disableDoubleClickZoom = disableDoubleClickZoom;
	    this.doubleClickZoomEnabled = doubleClickZoomEnabled;
	    this.enableContinuousZoom = enableContinuousZoom;
	    this.disableContinuousZoom = disableContinuousZoom;
	    this.continuousZoomEnabled = continuousZoomEnabled;
	    this.enableScrollWheelZoom = enableScrollWheelZoom;
	    this.disableScrollWheelZoom = disableScrollWheelZoom;
	    this.scrollWheelZoomEnabled = scrollWheelZoomEnabled;
	    
	    this.isLoaded = isLoaded;
	    this.getCenter = getCenter;
	    this.getBounds = getBounds;
	    this.getDirectionBounds = getDirectionBounds;
	    this.getBoundsZoomLevel = getBoundsZoomLevel;
	    this.getBoundsAtCenterLevel = getBoundsAtCenterLevel;
	    this.getSize = getSize;
	    this.getLevel = getLevel;
        
        this.setCenter = setCenter;
        this.panBy = panBy;
        this.panTo = panTo;
        this.panDirection = panDirection;
        this.zoomIn = zoomIn;
        this.zoomOut = zoomOut;
        this.zoomFit = zoomFit;
        this.zoomToLevel = zoomToLevel;
        this.saveCurrentPosition = saveCurrentPosition;
        this.goToSavedPosition = goToSavedPosition;
        this.fitOverlays = fitOverlays;
        this.fitMultiOverlays = fitMultiOverlays;
        this.checkResize = checkResize;
        
        this.addControl = addControl;
        this.removeControl = removeControl;
        this.getContainer = getContainer;
        
        this.addOverlay = addOverlay;
	    this.removeOverlay = removeOverlay;
	    this.clearOverlays = clearOverlays;
	    this.getOverlayContainer = getOverlayContainer;
	    
	    this.openInfoWindow = openInfoWindow;
	    this.openInfoWindowTabs = openInfoWindowTabs;
	    this.showMapBlowup = showMapBlowup;
	    this.updateInfoWindow = updateInfoWindow;
	    this.closeInfoWindow = closeInfoWindow;
	    this.getInfoWindow = getInfoWindow;
    	
	    this.fromLatLngToDivPixel = fromLatLngToDivPixel;
	    this.fromLatLngToContainerPixel = fromLatLngToContainerPixel;
	    this.fromDivPixelToLatLng = fromDivPixelToLatLng;
	    this.fromContainerPixelToLatLng = fromContainerPixelToLatLng;
	    this.fromContainerPixelToDivPixel = fromContainerPixelToDivPixel;
	    this.fromDivPixelToContainerPixel = fromDivPixelToContainerPixel;
	    this.vType = function(){ return "GeneralMap" };
        
        function hideControls()
        {
            this.mapObj.hideControls();
            /*for (var i = 0; i < this.nControls; i++)
                if (this.arrControls[i].hide != undefined)
                    this.arrControls[i].hide();*/
        }
        
        function showControls()
        {
            this.mapObj.showControls();
             /*for (var i = 0; i < this.nControls; i++)
                if (this.arrControls[i].show != undefined)
                    this.arrControls[i].show();*/
        }
        
        function enableDragging()
        {
            this.mapObj.enableDragging();
        }
        
        function disableDragging()
        {
            this.mapObj.disableDragging();
        }
        
        function draggingEnabled()
        {
            return this.mapObj.draggingEnabled();
        }
        
        function enableInfoWindow()
        {
            this.mapObj.enableInfoWindow();
        }
        
        function disableInfoWindow()
        {
            this.mapObj.disableInfoWindow();
        }
        
        function infoWindowEnabled()
        {
            return this.mapObj.infoWindowEnabled();
        }
        
        function enableDoubleClickZoom()
        {
            this.mapObj.enableDoubleClickZoom();
        }
        
        function disableDoubleClickZoom()
        {
            this.mapObj.disableDoubleClickZoom();
        }
        
        function doubleClickZoomEnabled()
        {
            return this.mapObj.doubleClickZoomEnabled();
        }
        
        function enableContinuousZoom()
        {
            this.mapObj.enableContinuousZoom();
        }
        
        function disableContinuousZoom()
        {
            this.mapObj.disableContinuousZoom();
        }
        
        function continuousZoomEnabled()
        {
            return this.mapObj.continuousZoomEnabled();
        }
        
        function enableScrollWheelZoom()
        {
            this.mapObj.enableScrollWheelZoom();
        }
        
        function disableScrollWheelZoom()
        {
            this.mapObj.disableScrollWheelZoom();
        }
        
        function scrollWheelZoomEnabled()
        {
            return this.mapObj.scrollWheelZoomEnabled();
        }
        
        function isLoaded()
        {
            return this.mapObj.isLoaded();
        }
        
        function getCenter()
        {
            return this.mapObj.getCenter();
        }
        
        function getBounds()
        {
            return this.mapObj.getBounds();
        }
        
        function getDirectionBounds()
        {
            if (GeneralMap.mapType == GeneralMap.MapType.VietbandoMap)
            {
                return this.mapObj.getDirectionBounds();
            }
            else
            {
                if (this.getLevel() <= 0)
                {
                    return this.getBounds();
                }
                else
                {
                    var ptNW = this.mapObj.fromContainerPixelToLatLng(new GPoint(-this.mapContainer.offsetWidth * 2, -this.mapContainer.offsetHeight * 2));
                    var ptSE = this.mapObj.fromContainerPixelToLatLng(new GPoint(this.mapContainer.offsetWidth * 3, this.mapContainer.offsetHeight * 3));
                    return new GeneralMap.LatLngBounds(ptNW, ptSE);
                }
            }   
        }
        
        function getBoundsZoomLevel(bounds)
        {
            return this.mapObj.getBoundsZoomLevel(bounds);
        }
        
        function getBoundsAtCenterLevel(center, level)
        {
            if (GeneralMap.mapType == GeneralMap.MapType.VietbandoMap)
            {
                return this.mapObj.getBoundsAtCenterLevel(center, level);
            }
            else
            {
                level += 5;
	            var ptV = GProjection.fromLatLngToPixel(center, level);
                var vx = ptV.x;
                var vy = ptV.y;
                var tempStartY = parseInt((vy - parseFloat(parseInt(this.mapContainer.offsetHeight)/2))/256);
                var tempStartX = parseInt((vx - parseFloat(parseInt(this.mapContainer.offsetWidth)/2))/256);
                var tempLeft = -parseInt((vx - parseFloat(parseInt(this.mapContainer.offsetWidth)/2))%256);
                var tempTop = -parseInt((vy - parseFloat(parseInt(this.mapContainer.offsetHeight)/2))%256);
                if (vx < parseInt(this.mapContainer.offsetWidth)/2)
                {
                    tempStartX--;
                    tempLeft -= 256;
                }
                
                if (vy < parseInt(this.mapContainer.offsetHeight)/2)
                {
                    tempStartY--;
                    tempTop -= 256;
                }
                
                var x = -this.mapContainer.offsetWidth * 2 + 256*tempStartX - tempLeft;
                var y = -this.mapContainer.offsetHeight * 2 + 256*tempStartY - tempTop;
                var ptR = GProjection.fromPixelToLatLng(new GPoint(x, y), level);
                var ptNW = new GLatLng(ptR.lat(), ptR.lng());
                
                x = this.mapContainer.offsetWidth * 3 + 256*tempStartX - tempLeft;
                y = this.mapContainer.offsetHeight * 3 + 256*tempStartY - tempTop;
                ptR = GProjection.fromPixelToLatLng(new GPoint(x, y), level);
                var ptSE = new GLatLng(ptR.lat(), ptR.lng());
                
                return new GeneralMap.LatLngBounds(ptNW, ptSE);
            }
        }
        
        function getSize()
        {
            return this.mapObj.getSize();
        }
        
        function getLevel()
        {
            if (GeneralMap.mapType == GeneralMap.MapType.VietbandoMap)
            {
                return this.mapObj.getLevel();
            }
            else
            {
                return this.mapObj.getZoom() - 5;
            }
        }
        
        function setCenter(center, level)
        {
            if (GeneralMap.mapType == GeneralMap.MapType.GoogleMap)
                level += 5;
            this.mapObj.setCenter(center, level);
        }
        
        function panBy(distance)
        {
            this.mapObj.panBy(distance);
        }
        
        function panTo(center)
        {
            this.mapObj.panTo(center);
        }
        
        function panDirection(dx, dy)
        {
            this.mapObj.panDirection(dx, dy);
        }
        
        function zoomIn()
        {
            this.mapObj.zoomIn();
        }
        
        function zoomOut()
        {
            this.mapObj.zoomOut();
        }
        
        function zoomFit()
        {
            if (GeneralMap.mapType == GeneralMap.MapType.VietbandoMap)
            {
                this.mapObj.zoomFit();
            }
            else
            {
                this.mapObj.setCenter(new GLatLng(14.102783, 109.649506), 5);
            }
        }
        
        function zoomToLevel(level)
        {
            if (GeneralMap.mapType == GeneralMap.MapType.VietbandoMap)
            {
                this.mapObj.zoomToLevel(level);
            }
            else
            {
                this.mapObj.setZoom(level + 5);
            }
        }
        
        function saveCurrentPosition()
        {
            if (GeneralMap.mapType == GeneralMap.MapType.VietbandoMap)
            {
                this.mapObj.saveCurrentPosition();
            }
            else
            {
                this.mapObj.savePosition();
            }
        }
        
        function goToSavedPosition()
        {
            if (GeneralMap.mapType == GeneralMap.MapType.VietbandoMap)
            {
                this.mapObj.goToSavedPosition();
            }
            else
            {
                this.mapObj.returnToSavedPosition();
            }
        }
        
        function fitOverlays()
        {
            if (GeneralMap.mapType == GeneralMap.MapType.VietbandoMap)
            {
                this.mapObj.fitOverlays();
            }
            else
            {
                if (this.nOverlays == 0)
                {
                    this.mapObj.setCenter(new GLatLng(14.102783, 109.649506), 5);
                    return;
                }
                
                var bounds = new GLatLngBounds();
                for (var i = 0; i < this.nOverlays; i++)
                {
                    if (this.arrOverlays[i].vType() == "VMarker")
                    {
                        bounds.extend(this.arrOverlays[i].getLatLng());
                    }
                    else
                    {
                        var pBounds = this.arrOverlays[i].getBounds();
                        bounds.extend(pBounds.getNorthWest());
                        bounds.extend(pBounds.getSouthEast());
                    }   
                }
                this.mapObj.setCenter(bounds.getCenter(), this.mapObj.getBoundsZoomLevel(bounds));
            }
        }
        
        function fitMultiOverlays(arrFitOverlays)
        {
            if (GeneralMap.mapType == GeneralMap.MapType.VietbandoMap)
            {
                this.mapObj.fitMultiOverlays(arrFitOverlays);
            }
            else
            {
                var bounds = new GLatLngBounds();
                for (var i = 0; i < arrFitOverlays.length; i++)
                {
                    if (arrFitOverlays[i].vType() == "VMarker")
                    {
                        bounds.extend(arrFitOverlays[i].getLatLng());
                    }
                    else
                    {
                        var pBounds = arrFitOverlays[i].getBounds();
                        bounds.extend(pBounds.getNorthWest());
                        bounds.extend(pBounds.getSouthEast());
                    }   
                }
                this.mapObj.setCenter(bounds.getCenter(), this.mapObj.getBoundsZoomLevel(bounds));
            }
        }
        
        function checkResize(preserveHSide, preserveVSide)
        {
            if (GeneralMap.mapType == GeneralMap.MapType.VietbandoMap)
            {
                this.mapObj.checkResize(preserveHSide, preserveVSide);
            }
            else
            {
                if (preserveHSide == undefined)
                    preserveHSide = 0;
                if (preserveVSide == undefined)
                    preserveVSide = 0;
                
                var dx, dy;
                if (preserveHSide == 1)
                    dx = (this.mapContainer.offsetWidth - this.prevWidth) / 2;
                else
                    dx = (this.prevWidth - this.mapContainer.offsetWidth) / 2;
                if (preserveVSide == 1)
                    dy = (this.mapContainer.offsetHeight - this.prevHeight) / 2;
                else
                    dy = (this.prevHeight - this.mapContainer.offsetHeight) / 2;
                var vx, vy;
                var ptV = this.mapObj.fromLatLngToContainerPixel(this.mapObj.getCenter());
                vx = ptV.x + dx;
                vy = ptV.y + dy;
                var ptR = this.mapObj.fromContainerPixelToLatLng(new GPoint(vx, vy));
                this.mapObj.checkResize();
                this.mapObj.setCenter(ptR, this.mapObj.getZoom());
                for (var i = 0; i < this.nControls; i++)
                    if (this.arrControls[i].vType != undefined && this.arrControls[i].vType() == "MapToolbar")
                        this.arrControls[i].redraw();
                
                this.prevWidth = this.mapContainer.offsetWidth;
                this.prevHeight = this.mapContainer.offsetHeight;
            }
        }
        
        function addControl(control, position)
        {
            this.mapObj.addControl(control, position);
            
            if (GeneralMap.mapType != GeneralMap.MapType.VietbandoMap)
            {
                if (control.vType != undefined && control.vType() == "VOverviewMapControl")
                {
                    var mObj = this.mapObj;
                    setTimeout(function(){
                            control.setMapType(mObj.getCurrentMapType());
                            var omap = (document.getElementById("container_overview") != undefined) ? document.getElementById("container_overview").childNodes[0] : null;
                            if (omap != null)
                            {
                                omap.style.backgroundColor = "#ffffff";
                                omap.style.borderTop = "1px solid rgb(122, 195, 236)";
                                omap.style.borderLeft = "1px solid rgb(122, 195, 236)";
                                omap.childNodes[0].style.border = "1px solid rgb(122, 195, 236)";
                            }
                        }, 10000);
                }
                
                control.arrIndex = this.nControls;
                this.arrControls[this.nControls] = control;
                this.nControls++;
            }
        }
        
        function removeControl(control)
        {
            if (GeneralMap.mapType != GeneralMap.MapType.VietbandoMap)
            {
                for (var i = control.arrIndex; i < this.nControls - 1; i++)
                {
                    this.arrControls[i] = this.arrControls[i + 1];
                    this.arrControls[i].arrIndex = this.arrControls[i].arrIndex - 1;
                }
                this.nControls--;
                this.arrControls[this.nControls] = null;
            }
            
            this.mapObj.removeControl(control);
        }
        
        function getContainer()
        {
            this.mapObj.getContainer();
        }
        
        function addOverlay(overlay)
        {
            if (overlay.vType != undefined && (overlay.vType() == "VPolyline" || overlay.vType() == "VPolygon") && GeneralMap.mapType != GeneralMap.MapType.VietbandoMap)
            {
                overlay.map_ = this.mapObj;
                overlay.drawLines();
            }
            else
            {
                this.mapObj.addOverlay(overlay);
            }
            
            if (GeneralMap.mapType != GeneralMap.MapType.VietbandoMap)
            {
                overlay.arrIndex = this.nOverlays;
                this.arrOverlays[this.nOverlays] = overlay;
                this.nOverlays++;
                
                if (overlay.vType != undefined && overlay.vType() == "VMarker")
                {
                    if (overlay.borderStyle != "" && overlay.borderStyle != undefined)
                        overlay.V[0].style.border = overlay.borderStyle;
                    if (overlay.opacity != undefined && overlay.opacity > 0)
                    {
                        overlay.V[0].style.filter = 'alpha(opacity = ' + overlay.opacity + ')';
                        overlay.V[0].style.opacity = overlay.opacity / 100;
                    }
                }   
            }
        }
        
        function removeOverlay(overlay)
        {
            if (GeneralMap.mapType != GeneralMap.MapType.VietbandoMap)
            {
                for (var i = overlay.arrIndex; i < this.nOverlays - 1; i++)
                {
                    this.arrOverlays[i] = this.arrOverlays[i + 1];
                    this.arrOverlays[i].arrIndex = this.arrOverlays[i].arrIndex - 1;
                }
                this.nOverlays--;
                this.arrOverlays[this.nOverlays] = null;
            }
            
            if (overlay.vType != undefined && (overlay.vType() == "VPolyline" || overlay.vType() == "VPolygon") && GeneralMap.mapType != GeneralMap.MapType.VietbandoMap)
            {
                overlay.remove();
                overlay = null;
            }
            else
            {
                this.mapObj.removeOverlay(overlay);
            }
        }
        
        function clearOverlays()
        {
            this.mapObj.clearOverlays();
            this.nOverlays = 0;
        }
        
        function getOverlayContainer()
        {
            if (GeneralMap.mapType == GeneralMap.MapType.VietbandoMap)
            {
                return this.mapObj.getOverlayContainer();
            }
            else
            {
                return this.mapObj.getPane(G_MAP_MARKER_PANE);
            }
        }
        
        function openInfoWindow(point, content, opts)
        {
            if (GeneralMap.mapType == GeneralMap.MapType.VietbandoMap)
            {
                this.mapObj.openInfoWindow(point, content, opts);
            }
            else
            {
                this.mapObj.openInfoWindowHtml(point, content, opts);
                if (opts.maximizeWhenOpen)
                    this.mapObj.getInfoWindow().maximize();
            }
        }
        
        function openInfoWindowTabs(point, tabs, opts)
        {
            if (GeneralMap.mapType == GeneralMap.MapType.VietbandoMap)
            {
                this.mapObj.openInfoWindowTabs(point, tabs, opts);
            }
            else
            {
                this.mapObj.openInfoWindowTabsHtml(point, tabs, opts);
            }
        }
        
        function showMapBlowup(point, opts, title)
        {
            if (GeneralMap.mapType == GeneralMap.MapType.VietbandoMap)
            {
                this.mapObj.showMapBlowup(point, opts, title);
            }
            else
            {
                this.mapObj.showMapBlowup(point, opts);
            }
        }
        
        function updateInfoWindow(tabs, onUpdateFn)
        {
            this.mapObj.updateInfoWindow(tabs, onUpdateFn);
        }
        
        function closeInfoWindow()
        {
            this.mapObj.closeInfoWindow();
        }
        
        function getInfoWindow()
        {
            return this.mapObj.getInfoWindow();
        }
        
        function fromLatLngToDivPixel(latlng)
        {
            return this.mapObj.fromLatLngToDivPixel(latlng);
        }
        
        function fromLatLngToContainerPixel(latlng)
        {
            return this.mapObj.fromLatLngToContainerPixel(latlng);
        }
        
        function fromDivPixelToLatLng(point)
        {
            return this.mapObj.fromDivPixelToLatLng(point);
        }
        
        function fromContainerPixelToLatLng(point)
        {
            return this.mapObj.fromContainerPixelToLatLng(point);
        }
        
        function fromContainerPixelToDivPixel(point)
        {
            return this.mapObj.fromContainerPixelToDivPixel(point);
        }
        
        function fromDivPixelToContainerPixel(point)
        {
            return this.mapObj.fromContainerPixelToDivPixel(point);
        }
    },
    Marker : function(point, icon, inert)
    {
        if (GeneralMap.mapType == GeneralMap.MapType.VietbandoMap)
        {
            return new VMarker(point, icon, inert);
        }
        else
        {
            if (typeof point == 'string')
            {
                var strLL = point.split(',');
                point = new GLatLng(strLL[1], strLL[0]);
            }
            var gm;
            if (icon.vType != undefined && icon.vType() == "VIcon")
            {
                gm = new GMarker(point, {icon : icon, draggable : true, bouncy : false});
            }
            else
            {
                icon.draggable = true;
                icon.bouncy = false;
                gm = new GMarker(point, icon);
            }
            gm.disableDragging();
            
            gm.setIcon = function(icon){
                    gm.setImage(icon.image);
                };
            
            return gm;
        }
    },
    Point : function(x, y)
    {
        if (GeneralMap.mapType == GeneralMap.MapType.VietbandoMap)
            return new VPoint(x, y);
        else
            return new GPoint(x, y);
    },
    Polygon : function(latlngs, lineColor, lineWidth, fillColor, lineOpacity, fillOpacity, opts)
    {
        if (latlngs == undefined) return;
        this.latlngs = latlngs;
        this.lineColor = (lineColor == null) ? 'red' : lineColor;
        this.lineWidth = (lineWidth == null) ? 3 : lineWidth;
        this.fillColor = (fillColor == null) ? 'green' : fillColor;
        this.lineOpacity = (lineOpacity == null) ? 0.5 : lineOpacity;
        this.fillOpacity = (fillOpacity == null) ? 0.3 : fillOpacity;
        this.opts = opts;
        this.arrPolygons = new Array();
	    this.nPolygons = 0;
        this.bHidden = false;
        this.isDirectionObj = false;
        
        this.drawLines = drawLines;
        this.addLineHandlers = addLineHandlers;
        this.removeLineHandlers = removeLineHandlers;
        this.remove = remove;
        this.openInfoWindow = openInfoWindow;
        this.getCenterPoint = getCenterPoint;
        this.insertPoint = insertPoint;
        this.deletePoint = deletePoint;
        this.getVertex = getVertex;
        this.setVertex = setVertex;
        this.getVertexCount = getVertexCount;
        this.getLatLngs = getLatLngs;
        this.setLatLngs = setLatLngs;
        this.setStyle = setStyle;
        this.hide = hide;
        this.show = show;
        this.isHidden = isHidden;
        this.vType = vType;
        
        if (GeneralMap.mapType == GeneralMap.MapType.VietbandoMap)
        {
            return new VPolygon(latlngs, lineColor, lineWidth, fillColor, lineOpacity, fillOpacity, opts);
        }
        else
        {
            if (typeof this.latlngs == 'object')
            {
                if (typeof this.latlngs[0] == 'object' && this.latlngs[0].vType == undefined)
                {
                    this.isDirectionObj = true;
                    var rArr = new Array();
                    for (var i = 0; i < this.latlngs.length; i++)
                    {
                        rArr[i] = new Array();
                        for (var j = 0; j < this.latlngs[i].length; j += 2)
                        {
                            var ptR = new GLatLng(this.latlngs[i][j+1], this.latlngs[i][j]);
                            rArr[i].push(ptR);
                        }
                    }
                    this.latlngs = rArr;
                }
            }
            else if (typeof this.latlngs == 'string')
            {
                var rarr = this.latlngs.split(',');
                this.latlngs = new Array();
                var j = 0;
                for (var i = 0; i < rarr.length; i += 2)
                {
                    this.latlngs[j] = new GLatLng(parseFloat(rarr[i + 1]), parseFloat(rarr[i]));
                    j++;
                }
            }
        }
        
        function drawLines()
        {
            if (!this.bHidden)
            {
                var clipArr = new Array();
                if (this.isDirectionObj)
                    clipArr = this.latlngs;
                else
                    clipArr[0] = this.latlngs;
                
                this.remove();
                
                var bClick = (this.opts != undefined) ? this.opts.clickable : true;
                this.nPolygons = clipArr.length;
                for (var i = 0; i < clipArr.length; i++)
                {
                    this.arrPolygons[i] = new GPolygon(clipArr[i], this.lineColor, this.lineWidth, this.lineOpacity, this.fillColor, this.fillOpacity, { clickable : bClick });
                    this.arrPolygons[i].type = this.type;
				    this.arrPolygons[i].mmIndex = this.mmIndex;
				    this.arrPolygons[i].actionType = this.actionType;
                    this.map_.addOverlay(this.arrPolygons[i]);
                }
            }
        }
        
        function addLineHandlers(vEvent, handler)
        {
            for (var i = 0; i < this.nPolygons; i++)
                GEvent.addListener(this.arrPolygons[i], vEvent, handler);
        }
        
        function removeLineHandlers()
        {
            
        }
        
        function remove()
        {
            for (var i = 0; i < this.nPolygons; i++)
            {
                this.map_.removeOverlay(this.arrPolygons[i]);
                this.arrPolygons[i] = null;
            }
            this.nPolygons = 0;
        }
        
        function openInfoWindow(content, opts)
        {
            this.map_.openInfoWindowHtml(this.getCenterPoint(), content , opts);
        }
        
        function getCenterPoint()
        {
            if (this.isDirectionObj)
                return null;
            var cp = GeneralMap.Util.getCenterPoint(this.latlngs);
            if (!GeneralMap.Util.isInsidePolygon(cp, this.latlngs))
                return new GLatLng((this.latlngs[0].lat() + this.latlngs[1].lat()) / 2, (this.latlngs[0].lng() + this.latlngs[1].lng()) / 2);
            return cp;
        }
        
        function getVertex(index)
        {
            if (this.latlngs == null) return;
            
            if (this.isDirectionObj)
            {
                var i = 0;
                while (index >= this.latlngs[i].length)
                {
                    index -= this.latlngs[i].length;
                    i++;
                }
                return this.latlngs[i][index];
            }
            return this.latlngs[index];
        }
        
        function setVertex(index, latlng)
        {
            if (this.isDirectionObj)
                return;
            this.latlngs[index] = latlng.copy();
            if (index == 0)
                this.latlngs[this.latlngs.length - 1] = latlng.copy();
            this.drawLines();
            this.addLineHandlers(this.vEvent, this.handler);
        }
        
        function getVertexCount()
        {
            if (this.latlngs == null) return 0;
            
            if (this.isDirectionObj)
            {
                var vCount = 0;
                for (var i = 0; i < this.latlngs.length; i++)
                    vCount += this.latlngs[i].length;
                return vCount;
            }
            return this.latlngs.length;
        }
        
        function insertPoint(index, latlng)
        {
            if (this.isDirectionObj)
                return;
            if (index >= this.latlngs.length)
                return;
            var arrLL = new Array();
            var nLL = 0;
            for (var i = 0; i < this.latlngs.length; i++)
            {
                arrLL[nLL] = this.latlngs[i].copy();
                nLL++;
                if (i == index)
                {
                    arrLL[nLL] = latlng.copy();
                    nLL++;
                }
            }
            this.latlngs = arrLL;
            this.drawLines();
            this.addLineHandlers(this.vEvent, this.handler);
        }
        
        function deletePoint(index)
        {
            if (this.isDirectionObj)
                return;
            if (index >= this.latlngs.length)
                return;
            var arrLL = new Array();
            var nLL = 0;
            for (var i = 0; i < this.latlngs.length; i++)
            {
                if (i != index)
                {
                    arrLL[nLL] = this.latlngs[i].copy();
                    nLL++;
                }
            }
            if (index == 0)
                arrLL[nLL - 1] = arrLL[0].copy();
            this.latlngs = arrLL;
            this.drawLines();
            this.addLineHandlers(this.vEvent, this.handler);
        }
        
        function getLatLngs()
        {
            return this.latlngs;
        }
        
        function setLatLngs(latlngs)
        {
            this.latlngs = latlngs;
            if (this.isDirectionObj)
            {
                var rArr = new Array();
                for (var i = 0; i < this.latlngs.length; i++)
                {
                    rArr[i] = new Array();
                    for (var j = 0; j < this.latlngs[i].length; j += 2)
                    {
                        var ptR = new GLatLng(this.latlngs[i][j+1], this.latlngs[i][j]);
                        rArr[i].push(ptR);
                    }
                }
                this.latlngs = rArr;
            }
            else if (typeof this.latlngs == 'string')
            {
                var rarr = this.latlngs.split(',');
                this.latlngs = new Array();
                var j = 0;
                for (var i = 0; i < rarr.length; i += 2)
                {
                    this.latlngs[j] = new GLatLng(parseFloat(rarr[i + 1]), parseFloat(rarr[i]));
                    j++;
                }
            }
            this.drawLines();
            this.addLineHandlers(this.vEvent, this.handler);
        }
        
        function setStyle(lineColor, lineWidth, fillColor, lineOpacity, fillOpacity)
        {
            this.lineColor = (lineColor == null) ? 'red' : lineColor;
            this.lineWidth = (lineWidth == null) ? 1 : lineWidth;
            this.fillColor = (fillColor == null) ? 'red' : fillColor;
            this.lineOpacity = (lineOpacity == null) ? 0.5 : lineOpacity;
            this.fillOpacity = (fillOpacity == null) ? 0.5 : fillOpacity;
            this.drawLines();
            this.addLineHandlers(this.vEvent, this.handler);
        }
        
        function hide()
        {
            this.bHidden = true;
            for (var i = 0; i < this.nPolygons; i++)
                this.arrPolygons[i].hide();
        }
        
        function show()
        {
            for (var i = 0; i < this.nPolygons; i++)
                this.arrPolygons[i].show();
            this.bHidden = false;
        }
        
        function isHidden()
        {
            return this.bHidden;
        }
        
        function vType()
        {
            return "VPolygon";
        }
        //
    },
    Polyline : function(latlngs, lineColor, lineWidth, fillColor, opacity, opts)
    {
        if (latlngs == undefined) return;
        this.latlngs = latlngs;
        this.lineColor = (lineColor == undefined) ? 'red' : lineColor;
        this.lineWidth = (lineWidth == undefined) ? 3 : lineWidth;
        this.opacity = (opacity == undefined) ? 0.5 : opacity;
        this.opts = opts;
        this.arrPolylines = new Array();
        this.nPolylines = 0;
        this.bHidden = false;
        this.isDirectionObj = false;
        this.map_ = null;
        
        this.drawLines = drawLines;
        this.addLineHandlers = addLineHandlers;
        this.removeLineHandlers = removeLineHandlers;
        this.remove = remove;
        this.getBounds = getBounds;
        this.openInfoWindow = openInfoWindow;
        this.getCenterPoint = getCenterPoint;
        this.getVertex = getVertex;
        this.setVertex = setVertex;
        this.getVertexCount = getVertexCount;
        this.insertPoint = insertPoint;
        this.deletePoint = deletePoint;
        this.getLatLngs = getLatLngs;
        this.setLatLngs = setLatLngs;
        this.setStyle = setStyle;
        this.hide = hide;
        this.show = show;
        this.isHidden = isHidden;
        this.vType = vType;
        
        if (GeneralMap.mapType == GeneralMap.MapType.VietbandoMap)
        {
            return new VPolyline(latlngs, lineColor, lineWidth, fillColor, opacity, opts);
        }
        else
        {
            if (typeof this.latlngs == 'object')
            {
                if (typeof this.latlngs[0] == 'object' && this.latlngs[0].vType == undefined)
                {
                    this.isDirectionObj = true;
                    var rArr = new Array();
                    for (var i = 0; i < this.latlngs.length; i++)
                    {
                        rArr[i] = new Array();
                        for (var j = 0; j < this.latlngs[i].length; j += 2)
                        {
                            var ptR = new GLatLng(this.latlngs[i][j+1], this.latlngs[i][j]);
                            rArr[i].push(ptR);
                        }
                    }
                    this.latlngs = rArr;
                }
            }
            else if (typeof this.latlngs == 'string')
            {
                var rarr = this.latlngs.split(',');
                this.latlngs = new Array();
                var j = 0;
                for (var i = 0; i < rarr.length; i += 2)
                {
                    this.latlngs[j] = new GLatLng(parseFloat(rarr[i + 1]), parseFloat(rarr[i]));
                    j++;
                }
            }
        }
        
        function drawLines()
        {
            if (!this.bHidden)
            {
                var clipArr = new Array();
                if (this.isDirectionObj)
                    clipArr = this.latlngs;
                else
                    clipArr[0] = this.latlngs;
                
                this.remove();
                
                var bClick = (this.opts != undefined) ? this.opts.clickable : true;
                this.nPolylines = clipArr.length;
                for (var i = 0; i < clipArr.length; i++)
                {
                    this.arrPolylines[i] = new GPolyline(clipArr[i], this.lineColor, this.lineWidth, this.opacity, { clickable : bClick });
                    this.arrPolylines[i].type = this.type;
				    this.arrPolylines[i].mmIndex = this.mmIndex;
				    this.arrPolylines[i].actionType = this.actionType;
                    this.map_.addOverlay(this.arrPolylines[i]);
                }
            }
        }
        
        function addLineHandlers(vEvent, handler)
        {
            for (var i = 0; i < this.nPolylines; i++)
                GEvent.addListener(this.arrPolylines[i], vEvent, handler);
        }
        
        function removeLineHandlers()
        {
            
        }
        
        function remove()
        {
            for (var i = 0; i < this.nPolylines; i++)
            {
                this.map_.removeOverlay(this.arrPolylines[i]);
                this.arrPolylines[i] = null;
            }
            this.nPolylines = 0;
        }
        
        function getBounds()
        {
            var bounds = new GLatLngBounds();
            var pBound;
            for (var i = 0; i < this.nPolylines; i++)
            {
                pBound = this.arrPolylines[i].getBounds();
                bounds.extend(pBound.getNorthEast());
                bounds.extend(pBound.getSouthWest());
            }
            return bounds;
        }
        
        function openInfoWindow(content, opts)
        {
            this.map_.openInfoWindowHtml(this.getCenterPoint(), content , opts);
        }
        
        function getCenterPoint()
        {
            if (this.isDirectionObj)
                return null;
            var lat, lng;
            if (this.latlngs.length % 2 == 0)
            {
                var ic = parseInt(this.latlngs.length / 2) - 1;
                lat = (this.latlngs[ic].lat() + this.latlngs[ic + 1].lat()) / 2;
                lng = (this.latlngs[ic].lng() + this.latlngs[ic + 1].lng()) / 2;
            }
            else
            {
                var ic = parseInt(this.latlngs.length / 2);
                lat = this.latlngs[ic].lat();
                lng = this.latlngs[ic].lng();
            }
            return new GLatLng(lat, lng);
        }
        
        function getVertex(index)
        {
            if (this.latlngs == null) return;
            
            if (this.isDirectionObj)
            {
                var i = 0;
                while (index >= this.latlngs[i].length)
                {
                    index -= this.latlngs[i].length;
                    i++;
                }
                return this.latlngs[i][index];
            }
            return this.latlngs[index];
        }
        
        function setVertex(index, latlng)
        {
            if (this.isDirectionObj)
                return;
            this.latlngs[index] = latlng.copy();
            this.drawLines();
            this.addLineHandlers(this.vEvent, this.handler);
        }
        
        function getVertexCount()
        {
            if (this.latlngs == null) return 0;
            
            if (this.isDirectionObj)
            {
                var vCount = 0;
                for (var i = 0; i < this.latlngs.length; i++)
                    vCount += this.latlngs[i].length;
                return vCount;
            }
            return this.latlngs.length;
        }
        
        function insertPoint(index, latlng)
        {
            if (this.isDirectionObj)
                return;
            if (index >= this.latlngs.length)
                return;
            var arrLL = new Array();
            var nLL = 0;
            for (var i = 0; i < this.latlngs.length; i++)
            {
                arrLL[nLL] = this.latlngs[i].copy();
                nLL++;
                if (i == index)
                {
                    arrLL[nLL] = latlng.copy();
                    nLL++;
                }
            }
            this.latlngs = arrLL;
            this.drawLines();
            this.addLineHandlers(this.vEvent, this.handler);
        }
        
        function deletePoint(index)
        {
            if (this.isDirectionObj)
                return;
            if (index >= this.latlngs.length)
                return;
            var arrLL = new Array();
            var nLL = 0;
            for (var i = 0; i < this.latlngs.length; i++)
            {
                if (i != index)
                {
                    arrLL[nLL] = this.latlngs[i].copy();
                    nLL++;
                }
            }
            this.latlngs = arrLL;
            this.drawLines();
            this.addLineHandlers(this.vEvent, this.handler);
        }
        
        function getLatLngs()
        {
            return this.latlngs;
        }
        
        function setLatLngs(latlngs)
        {
            this.latlngs = latlngs;
            if (this.isDirectionObj)
            {
                var rArr = new Array();
                for (var i = 0; i < this.latlngs.length; i++)
                {
                    rArr[i] = new Array();
                    for (var j = 0; j < this.latlngs[i].length; j += 2)
                    {
                        var ptR = new GLatLng(this.latlngs[i][j+1], this.latlngs[i][j]);
                        rArr[i].push(ptR);
                    }
                }
                this.latlngs = rArr;
            }
            else if (typeof this.latlngs == 'string')
            {
                var rarr = this.latlngs.split(',');
                this.latlngs = new Array();
                var j = 0;
                for (var i = 0; i < rarr.length; i += 2)
                {
                    this.latlngs[j] = new GLatLng(parseFloat(rarr[i + 1]), parseFloat(rarr[i]));
                    j++;
                }
            }
            this.drawLines();
            this.addLineHandlers(this.vEvent, this.handler);
        }
        
        function setStyle(lineColor, lineWidth, fillColor, opacity)
        {
            this.lineColor = (lineColor == undefined) ? 'red' : lineColor;
            this.lineWidth = (lineWidth == undefined) ? 1 : lineWidth;
            this.fillColor = (fillColor == undefined) ? 'red' : fillColor;
            this.opacity = (opacity == undefined) ? 1 : opacity;
            this.drawLines();
            this.addLineHandlers(this.vEvent, this.handler);
        }
        
        function hide()
        {
            this.bHidden = true;
            for (var i = 0; i < this.nPolylines; i++)
                this.arrPolylines[i].hide();
        }
        
        function show()
        {
            for (var i = 0; i < this.nPolylines; i++)
                this.arrPolylines[i].show();
            this.bHidden = false;
        }
        
        function isHidden()
        {
            return this.bHidden;
        }
        
        function vType()
        {
            return "VPolyline";
        }
    },
    Projection : {
        fromLatLngToPixel : function(latlng, zoomlevel)
        {
            if (GeneralMap.mapType == GeneralMap.MapType.VietbandoMap)
                return VProjection.fromLatLngToPixel(latlng, zoomlevel);
            else
                return GProjection.fromLatLngToPixel(latlng, zoomlevel);
        },
        fromPixelToLatLng : function(point, zoomlevel)
        {
            if (GeneralMap.mapType == GeneralMap.MapType.VietbandoMap)
                return VProjection.fromPixelToLatLng(point, zoomlevel);
            else
                return GProjection.fromPixelToLatLng(point, zoomlevel);
        }
    },
    Text : function(latlngs, text, textStyle, textOptions)
    {
        this.latlngs = latlngs;
        this.text = (text != undefined) ? text : 'vietbando';
        this.textStyle = (textStyle != undefined) ? textStyle : new GeneralMap.TextStyle();
        this.textOptions = (textOptions != undefined) ? textOptions : new GeneralMap.TextOptions();
        
        this.initialize = initialize;
        this.createText = createText;
        this.remove = remove;
        this.copy = copy;
        this.redraw = redraw;
        this.openInfoWindow = openInfoWindow;
        this.enableDragging = enableDragging;
        this.disableDragging = disableDragging;
        this.getLatLng = getLatLng;
        this.setText = setText;
        this.hide = hide;
        this.show = show;
        this.isHidden = isHidden;
        this.vType = vType;
        
        if (GeneralMap.mapType == GeneralMap.MapType.VietbandoMap)
        {
            return new VText(latlngs, text, textStyle, textOptions);
        }
        else
        {
            if (typeof this.latlngs == 'string')
            {
                var strLL = this.latlngs.split(',');
                this.latlngs = new GLatLng(strLL[1], strLL[0]);
            }
        }
        
        function initialize(map)
        {
            this.map_ = map;
            this.createText(map, false);
        }
        
        function createText(map, redraw)
        {
            var divText;
            if (!redraw)
            {
                divText = document.createElement("div");
                this.id = map.id + "_VText";
                divText.id = map.id + "_VText";
                divText.style.overflow = "visible";
                divText.style.position = "absolute";
                divText.className = 'dragtext';
                divText.objMan = this;
                map.getPane(G_MAP_MARKER_PANE).appendChild(divText);
                this.div_ = divText;
            }
            else
                divText = this.div_;
            
            var strHTML = "<a id='" + map.id + "_VTextCt' style='cursor:pointer; font-size:" + this.textStyle.fontSize + "px; font-weight:" + this.textStyle.fontWeight + "; color:" + this.textStyle.color + "; font-family:" + this.textStyle.fontFamily + ";'>" + this.text + "</a>";
            divText.innerHTML = strHTML;
            
            var divTemp = document.createElement('div');
            divTemp.id = 'divtemp';
            divTemp.innerHTML = strHTML;
            divTemp.style.overflow = 'visible';
            divTemp.style.position = 'absolute';
            document.body.appendChild(divTemp);
            var divWidth = divTemp.offsetWidth;
            var divHeight = divTemp.offsetHeight;
            document.body.removeChild(divTemp);
            
            divText.style.width = divWidth + 'px';
            divText.style.height = divHeight + 'px';
            if (this.textOptions.offset == null)
                this.textOptions.offset = new VSize(this.div_.offsetWidth/2, this.div_.offsetHeight/2);
            this.redraw();
        }
        
        function remove()
        {
            this.div_.parentNode.removeChild(this.div_);
        }
        
        function copy()
        {
            return new GeneralMap.Text(this.latlngs, this.text, this.textStyle);
        }
        
        function redraw()
        {
            var pt = this.map_.fromLatLngToDivPixel(this.latlngs);
            this.div_.style.left = (pt.x - this.textOptions.offset.width) + "px";
            this.div_.style.top = (pt.y - this.textOptions.offset.height) + "px";
        }
        
        function openInfoWindow(content, opts)
        {
            this.map_.openInfoWindow(this.latlngs, content);
        }
        
        function enableDragging()
        {
            //var objectToDrag = new GDraggableObject(this.div_, {draggingCursor: "pointer", draggableCursor: "pointer"});
            //GEvent.addListener(objectToDrag, "dragstart", function() { return false; });
            
            this.textOptions.draggable = true;
            this.div_.draggable = 1;
        }
        
        function disableDragging()
        {
            this.textOptions.draggable = false;
            this.div_.draggable = 0;
        }
        
        function getLatLng()
        {
            return this.latlngs;
        }
        
        function setText(text, textStyle, textOptions)
        {
            this.text = (text != undefined) ? text : 'vietbando';
            this.textStyle = (textStyle != undefined) ? textStyle : new GeneralMap.TextStyle();
            this.textOptions = (textOptions != undefined) ? textOptions : new GeneralMap.TextOptions();
            this.createText(this.map_, true);
        }
        
        function hide()
        {
            this.div_.style.visibility = 'hidden';
        }
        
        function show()
        {
            this.div_.style.visibility = 'visible';
        }
        
        function isHidden()
        {
            if (this.div_.style.visibility == 'hidden')
                return true;
            return false;
        }
        
        function vType()
        {
            return 'VText';
        }
    },
    TextOptions : function(draggable, offset)
    {
        return new VTextOptions(draggable, offset);
    },
    KeyboardHandler : function(map)
    {
        if (GeneralMap.mapType == GeneralMap.MapType.VietbandoMap)
            return new VKeyboardHandler(map);
        else
            return new GKeyboardHandler(map);
    },
    Arrow : function(latlngs, position, color, width, opacity)
    {
        if (latlngs == undefined) return;
        this.latlngs = latlngs;
        this.position = (position == undefined) ? 'end' : position;
        this.color = (color == undefined) ? 'red' : color;
        this.width = (width == undefined) ? 3 : (width + 1);
        this.opacity = (opacity == undefined) ? 0.6 : opacity;
        this.arrArrows = new Array();
        this.nArrows = 0;
        this.bHidden = false;
        this.isDirectionObj = false;
        
        this.drawLines = drawLines;
        this.drawArrow = drawArrow;
        this.remove = remove;
        this.setLatLngs = setLatLngs;
        this.hide = hide;
        this.show = show;
        this.isHidden = isHidden;
        this.vType = vType;
        
        if (GeneralMap.mapType == GeneralMap.MapType.VietbandoMap)
        {
            return new VArrow(latlngs, position, color, width, opacity);
        }
        else
        {
            if (typeof this.latlngs == 'object')
            {
                if (typeof this.latlngs[0] == 'object' && this.latlngs[0].vType == undefined)
                {
                    this.isDirectionObj = true;
                    var rArr = new Array();
                    for (var i = 0; i < this.latlngs.length; i++)
                    {
                        rArr[i] = new Array();
                        for (var j = 0; j < this.latlngs[i].length; j += 2)
                        {
                            var ptR = new GLatLng(this.latlngs[i][j+1], this.latlngs[i][j]);
                            rArr[i].push(ptR);
                        }
                    }
                    this.latlngs = rArr;
                }
            }
            else if (typeof this.latlngs == 'string')
            {
                var rarr = this.latlngs.split(',');
                this.latlngs = new Array();
                var j = 0;
                for (var i = 0; i < rarr.length; i += 2)
                {
                    this.latlngs[j] = new GLatLng(parseFloat(rarr[i + 1]), parseFloat(rarr[i]));
                    j++;
                }
            }
        }
        
        function drawLines()
        {
            if (!this.bHidden)
            {
                var clipArr = new Array();
                if (this.isDirectionObj)
                    clipArr = this.latlngs;
                else
                    clipArr[0] = this.latlngs;
                
                this.remove();
                this.nArrows = 0;
                
                var x1, y1, x2, y2, preX, preY, bDraw = true;
                for (var k = 0; k < clipArr.length; k++)
                    for (var i = 0; i < clipArr[k].length - 1; i++)
                    {
                        bDraw = true;
                        var pt = this.map_.fromLatLngToDivPixel(clipArr[k][i]);
                        x1 = pt.x;
                        y1 = pt.y;
                        pt = this.map_.fromLatLngToDivPixel(clipArr[k][i+1]);
                        x2 = pt.x;
                        y2 = pt.y;
                        
                        if (i == 0)
                        {
                            preX = x2;
                            preY = y2;
                        }
                        else
                        {
                            if (VUtil.Distance(preX, preY, x2, y2) < 10000 || VUtil.Distance(x1, y1, x2, y2) < 600)
                            {
                                bDraw = false;
                            }
                            else
                            {
                                preX = x2;
                                preY = y2;
                            }
                        }
                        
                        if (bDraw && VUtil.Distance(x1, y1, x2, y2) != 0)
                        {
                            var arrPts = this.drawArrow(x1, y1, x2, y2);
                            this.arrArrows[this.nArrows] = new GPolygon(arrPts, this.color, this.width, this.opacity, this.color, this.opacity);
                            this.map_.addOverlay(this.arrArrows[this.nArrows]);
                            this.nArrows++;
                        }
                    }
            }
        }
        
        function drawArrow(x, y, xx, yy)
        {
            var arrowWidth = 10.0;
            var theta = 0.823;
            var xPoints = [];
            var yPoints = [];
            var vecLine = [];
            var vecLeft = [];
            var fLength;
            var th;
            var ta;
            var baseX, baseY;
            
            xPoints[ 0 ] = xx;
            yPoints[ 0 ] = yy;
         
            // build the line vector
            vecLine[ 0 ] = xPoints[ 0 ] - x;
            vecLine[ 1 ] = yPoints[ 0 ] - y;
         
            // build the arrow base vector - normal to the line
            vecLeft[ 0 ] = -vecLine[ 1 ];
            vecLeft[ 1 ] = vecLine[ 0 ];
         
            // setup length parameters
            fLength = Math.sqrt( vecLine[0] * vecLine[0] + vecLine[1] * vecLine[1] );
            th = arrowWidth / ( 2.0 * fLength );
            ta = arrowWidth / ( 2.0 * ( Math.tan( theta ) / 2.0 ) * fLength );
         
            // find the base of the arrow
            baseX = xPoints[ 0 ] - ta * vecLine[0];
            baseY = yPoints[ 0 ] - ta * vecLine[1];
         
            // build the points on the sides of the arrow
            xPoints[ 1 ] = baseX + th * vecLeft[0];
            yPoints[ 1 ] = baseY + th * vecLeft[1];
            xPoints[ 2 ] = baseX - th * vecLeft[0];
            yPoints[ 2 ] = baseY - th * vecLeft[1];
            
            return [ this.map_.fromDivPixelToLatLng(new GPoint(baseX, baseY)), this.map_.fromDivPixelToLatLng(new GPoint(xPoints[1], yPoints[1])), this.map_.fromDivPixelToLatLng(new GPoint(xPoints[0], yPoints[0])), this.map_.fromDivPixelToLatLng(new GPoint(xPoints[2], yPoints[2])), this.map_.fromDivPixelToLatLng(new GPoint(baseX, baseY)) ];
        }
        
        function remove()
        {
            for (var i = 0; i < this.nArrows; i++)
            {
                this.map_.removeOverlay(this.arrArrows[i]);
                this.arrArrows[i] = null;
            }
            this.nArrows = 0;
        }
        
        function setLatLngs(latlngs)
        {
            this.latlngs = latlngs;
            if (this.isDirectionObj)
            {
                var rArr = new Array();
                for (var i = 0; i < this.latlngs.length; i++)
                {
                    rArr[i] = new Array();
                    for (var j = 0; j < this.latlngs[i].length; j += 2)
                    {
                        var ptR = new GLatLng(this.latlngs[i][j+1], this.latlngs[i][j]);
                        rArr[i].push(ptR);
                    }
                }
                this.latlngs = rArr;
            }
            else if (typeof this.latlngs == 'string')
            {
                var rarr = this.latlngs.split(',');
                this.latlngs = new Array();
                var j = 0;
                for (var i = 0; i < rarr.length; i += 2)
                {
                    this.latlngs[j] = new GLatLng(parseFloat(rarr[i + 1]), parseFloat(rarr[i]));
                    j++;
                }
            }
            this.drawLines();
        }
        
        function hide()
        {
            this.bHidden = true;
            for (var i = 0; i < this.nArrows; i++)
                this.arrArrows[i].hide();
        }
        
        function show()
        {
            for (var i = 0; i < this.nArrows; i++)
                this.arrArrows[i].show();
            this.bHidden = false;
        }
        
        function isHidden()
        {
            return this.bHidden;
        }
        
        function vType()
        {
            return "VPolyline";
        }
    }
};

if (GeneralMap.mapType == GeneralMap.MapType.GoogleMap)
    GeneralMap.Text.prototype = new GOverlay();