function MapItem(id, type, strokeColor, fillColor, icon) {

    this.id = id;
    this.type = type;   // 1=icon, 2=line, 3=polygon
    this.strokeColor = strokeColor;
    this.fillColor = fillColor;
    this.icon = icon;
    this.centerLatitude = null;
    this.centerLongitude = null;
    this.zoomLevel = null;

    this.overlay = null;

    // array of GLatLng
    this.points = new Array();
}

var MapUtils = {

    /* Settings */
    gMap        : null,
    gMapType    : G_NORMAL_MAP ,
    gMapCenter  : new GLatLng(22.313664, 114.22484),
    gMapZoom    : 19,

    /* Data */
    items       : new Array(),  /* array of MapItem */
    topics      : {},
    ids         : {},
    atype       : {},
    subdomain   : {},
    /* Dom */
    menu        : null,

    getGMap: function() {
        return this.gMap;
    },

    display: function(id, centerLatitude, centerLongitude, zoomLevel) {
        var obj = document.getElementById(id);

        if (typeof obj == "object" && GBrowserIsCompatible()) {
            this.gMap = new GMap2(obj);
            this.gMap.setCenter(new GLatLng(centerLatitude, centerLongitude), zoomLevel, this.gMapType);
            this.gMap.addControl(new GSmallMapControl());
            this.gMap.addControl(new GMapTypeControl());

            GEvent.addListener(this.gMap, "click", function(marker,point) {
                // alert(point);
            });
        }

        // better to unload them
        jQuery(window).bind('unload', this.unload);
    },

    load: function(id, str) {
        var obj = document.getElementById(id);

        if (typeof obj == "object" && GBrowserIsCompatible()) {
            this.gMap = new GMap2(obj);
            this.gMap.setCenter(this.gMapCenter, this.gMapZoom, this.gMapType);
            this.gMap.addControl(new GSmallMapControl());
            this.gMap.addControl(new GMapTypeControl());
            // this.gMap.enableContinuousZoom();
            // this.gMap.enableScrollWheelZoom();

            GEvent.addListener(this.gMap, "click",
                    function(marker, point) {
                        if (marker) {
                            MapUtils.getGMap().removeOverlay(marker);
                            MapUtils.removePoint(MapUtils.getCurrentItem(), point, marker);
                        } else {
                            if (MapUtils.items.length >0) {
                                MapUtils.addPoint(MapUtils.getCurrentItem(), point);

                                if (MapUtils.getCurrentItem().icon != null) {
                                    var icon = new GIcon();
                                    var p = window.location.href.split("\/");
                                    p.splice(p.length-1, 1);
                                    icon.image = p.join("\/") + "/imgs/admin/emoticons/mark_"+ MapUtils.getCurrentItem().icon +".png";
                                    icon.shadow = p.join("\/") + "/imgs/admin/emoticons/transparent.png";
                                    // icon.shadow = "http://labs.google.com/ridefinder/images/mm_20_shadow.png";
                                    icon.iconSize = new GSize(20, 33);
                                    icon.shadowSize = new GSize(1, 1);
                                    icon.iconAnchor = new GPoint(18, 38);
                                    icon.infoWindowAnchor = new GPoint(5, 1);
                                    MapUtils.getGMap().addOverlay(new GMarker(point, icon));
                                } else {
                                    MapUtils.getGMap().addOverlay(new GMarker(point));
                                }
                            } else {
                                alert(str);
                            }
                        }
                    }
                );
        }

        // better to unload them
        jQuery(window).bind('unload', this.unload);
    },

    unload: function() {
        GUnload();
    },

    setMenu: function(obj) {
        this.menu = obj;
    },

    saveData: function() {
        // this.getCurrentItem().name = jQuery("#itemName").val();
        this.getCurrentItem().description = jQuery("#itemDescription").val();
        this.getCurrentItem().type = jQuery("#itemType").val();
        this.getCurrentItem().strokeColor = jQuery("#itemStrokeColor").val();
        this.getCurrentItem().fillColor = jQuery("#itemFillColor").val();
        this.getCurrentItem().icon = jQuery("#itemIcon").val();
    },

    loadData: function() {
        var item = this.getCurrentItem();
        jQuery("#itemDescription").val( item.description );
        jQuery("#itemType")[0].selectedIndex = item.type - 1;
        jQuery("#itemStrokeColor").val( item.strokeColor );
        jQuery("#itemFillColor").val( item.fillColor );
        jQuery("#itemIcon").val( item.icon );
    },

    setItemType: function(type) {
        this.getCurrentItem().type = type;
    },

    getCurrentItem: function() {
        if ( this.menu.selectedIndex != -1 ) {
            return this.items[this.menu.selectedIndex];
        } else {
            return false;
        }
    },

    newItem : function(type, strokeColor, fillColor, icon ) {
        var item = new MapItem(this.items.length, type, strokeColor,  fillColor, icon );

        this.items.push(item);
        this.currentItem++;
        this.menu.options[this.menu.options.length] = new Option(item.name, item.id);
        this.menu.selectedIndex = this.items.length-1;

        jQuery("#itemType").selectedIndex = 0;
        jQuery("#itemStrokeColor").val( strokeColor );
        jQuery("#itemFillColor").val( fillColor );
        jQuery("#itemIcon").val( type );

        return item;
    },

    removeItem: function(id) {
        var id = this.menu[this.menu.selectedIndex].value;
        for (var i=0; i<this.items.length; i++) {
            if (this.items[i].id == id) {
                this.items.splice(i,1);
                this.menu.options[i] = null;
                return;
            }
        }
    },

    addPoint : function(item, point) {
        var key = point.lat() + "-" + point.lng();
        eval('item.points.push({ "'+key+'": point}) ');
    },

    addPointUrl : function(item, point, subdomain, topics, ids, atype) {
        var key = point.lat() + "-" + point.lng();
        eval('item.points.push({ "'+key+'": point}) ');
        this.topics[key] = topics;
        this.ids[key] = ids;

        // Check for the article type contains multiple type
        var arr = atype.split(",");
        var h = {};
        var size = 0;
        for (var i=0; i < arr.length; i++) {
            if ( typeof h[arr[i]] == "undefined" ) {
                h[ arr[i] ] = arr[i];
                size++;
            }
        }

        if (size>1) {
            this.atype[key] = 99;
        } else {
            this.atype[key] = arr[i - 1];
        }

        this.subdomain[key] = subdomain;
    },

    removePoint : function(item, point, marker) {
        // this.clear();
        var key = marker.getPoint().lat() + "-" + marker.getPoint().lng();
        for (var i=0; i<item.points.length; i++) {
            var type = eval('typeof item.points[i]["'+key+'"]');
            if (type == "object" ) {
                item.points.splice(i,1);
                return;
            }
        }
    },

    getPointsGLatLng: function(item) {
        var points = new Array();
        for (var i=0; i<item.points.length; i++) {
            for (p in item.points[i]) {
                points.push( item.points[i][p] );
            }
        }
        return points;
    },

    addMarker: function(item, point, t) {

                    var icon = new GIcon();
                    var p = window.location.href.split("\/");
                    p.splice(p.length-1, 1);
                    var key = point.lat() + "-" + point.lng();
                    var atype = MapUtils.atype[key];

                    // icon.image = p.join("\/") + "/imgs/summary/emoticons/mark_"+ MapUtils.getCurrentItem().icon +".png";
                    icon.image = p.join("\/") + "/imgs/summary/emoticons/marker_"+ atype +".png";
                    icon.shadow = p.join("\/") + "/imgs/admin/emoticons/transparent.png";
                    // icon.shadow = "http://labs.google.com/ridefinder/images/mm_20_shadow.png";
                    icon.iconSize = new GSize(32, 40);
                    icon.shadowSize = new GSize(1, 1);
                    icon.iconAnchor = new GPoint(18, 38);
                    icon.infoWindowAnchor = new GPoint(5, 1);

                    if (t==1) {
                        icon.image = p.join("\/") + "/imgs/admin/emoticons/mark_3.png";
                        icon.iconSize = new GSize(24, 42);
                        icon.iconAnchor = new GPoint(20, 45);
                    }

                    var marker;
                    if (item.type==1) {
                        // marker = new GMarker(point, icon);
                        var opt = new Object();
                        opt.icon=icon;
                        opt.title="點擊這點";
                        marker = new GMarker(point, opt);

                    } else if (item.type==2) {
                        var opt = new Object();
                        opt.icon=icon;
                        opt.title="點擊這條線";
                        marker = new GMarker(point, opt);
                    } else {
                        var opt = new Object();
                        opt.icon=icon;
                        opt.title="點擊這面框";
                        marker = new GMarker(point, opt);
                    }

                    GEvent.addListener(marker, "click", function() {

                            var key = point.lat() + "-" + point.lng();
                            var topics = MapUtils.topics[key].split(",");
                            var ids = MapUtils.ids[key].split(",");
                            if (topics.length <1) {
                                    // TODO: Action to be triggered when click on marker

                                        viewPost(ids[0]);
                                    // window.open("http://"+MapUtils.subdomain[key]+".wanchaiinfo.hk/index.php?op=ViewArticle&articleId=" + ids[0]);
                                    // top.location.href="http://"+MapUtils.subdomain+".wanchaiinfo.hk/index.php?op=ViewArticle&articleId=" + ids[0];
                            } else {
                                var str = "";

                                for(var i=topics.length-1; i>=0 ;i--) {
                                    if (i < (topics.length-5)){break}
                                    str += " <div style='font-size:11px;text-align:left'> " +  " <a style='font-size:11px;color:#339999;font-family: Arial, Helvetica, sans-serif;'  href='javascript:viewPost(" + ids[i] + ")'>" + topics[i] + "</a><div>";
                                }

                                // TODO: Action to be triggered when click on marker, if more then one post
                                marker.openInfoWindowHtml(str);
                            }

                            // TODO: Action trigger when click the icon
                            // MapUtils.getGMap().removeOverlay(marker);
                            // MapUtils.addMarker(item, point, 1);

                        }
                    );
                    MapUtils.getGMap().addOverlay(marker);
    },

    addPoints: function(item) {
        if (item.overlay != null ) {
            this.gMap.removeOverlay(item.overlay);
        }
        for (var i=0; i<item.points.length; i++) {
            for (t in item.points[i]) {
                var point = item.points[i][t];
                if (MapUtils.getCurrentItem().icon != null) {
                    this.addMarker(item, point, 0);
                } else {
                    MapUtils.getGMap().addOverlay(new GMarker(point));
                }
            }
        }
    },

    addLine: function(item) {
        if (item.overlay != null) {
            this.clear(item);
        }

        item.overlay = new GPolyline(this.getPointsGLatLng(item), item.strokeColor, 5);
        this.gMap.addOverlay(  item.overlay  );
    },

    addPolygon: function(item) {
        if (item.overlay != null) {
            this.clear(item);
        }

        var points = this.getPointsGLatLng(item);
        points[points.length] = points[0];  // join the points

        item.overlay = new GPolygon(points, "#000000", 3,
                                    1, item.fillColor, 0.5);

        this.gMap.addOverlay( item.overlay );
    },

    clear   : function(item) {
        this.gMap.removeOverlay(item.overlay);
        item.points = Array();
    },

    clearAll: function() {
        this.gMap.clearOverlays();
        this.getCurrentItem().points = new Array();

    },

    debug: function() {
        console.debug( this.items );
    },

    render: function() {
        if ( jQuery("#itemStrokeColor").val() != null ) {
            this.getCurrentItem().strokeColor = jQuery("#itemStrokeColor").val();
        }

        if ( jQuery("#itemFillColor").val() != null ) {
            this.getCurrentItem().fillColor = jQuery("#itemFillColor").val();
        }
        if (this.getCurrentItem().type ==1) {
            this.addPoints(this.getCurrentItem());
        } else if (this.getCurrentItem().type == 2) {
            this.addLine(this.getCurrentItem());
        } else if (this.getCurrentItem().type == 3) {
            this.addPolygon(this.getCurrentItem());
        }
    },

    renderMore: function() {

        if ( this.getCurrentItem().type == 2 ||  this.getCurrentItem().type == 3) {
                this.getCurrentItem().points.splice(0,this.getCurrentItem().points.length-1);
                this.getCurrentItem().overlay = null;
                if ( this.getCurrentItem().type == 2) {
                    this.getCurrentItem().icon=99;
                } else {
                    this.getCurrentItem().icon=98;
                }
                this.addPoints(this.getCurrentItem());
        }

    },

    useIcon: function(iconId) {
        jQuery(".mapIcon").css("background-color", "#ffffff");
        jQuery("#mapIcon"+iconId).css("background-color", "#dedede");
        this.getCurrentItem().icon = iconId;
    },

    finish: function(obj, msg) {
        this.items[0].centerLatitude =  this.gMap.getCenter().y;
        this.items[0].centerLongitude =  this.gMap.getCenter().x;
        this.items[0].zoomLevel = this.gMap.getZoom();
        this.items[0].overlay = "";

        if (jQuery("#mapName").val() == "" || this.items[0].points.length ==0) {
            alert(msg); jQuery("#mapName").focus();
        } else {
            jQuery("#jsonMapItems").val( JSON.stringify( this.items[0] ) );
            obj.submit();
        }
    }
}
