/**
 * Destination map widget
 *
 * @author dettier
 */

(function () {

    var ampPattern = /&amp;/g;

    var contains = function(poly, point) {
        var i, j;
        var xi, yi, xj, yj;
        var oddNodes = false;
        var x = point.lng();
        var y = point.lat();
        var vertexCount = poly.getVertexCount() - 1;

        for (i = 0, j = 0; i <= vertexCount; i++) {

            j = (j >= vertexCount) ? 0 : j + 1;

            yi = poly.getVertex(i).lat();
            yj = poly.getVertex(j).lat();

            if ((yi < y && yj >= y) || (yj < y && yi >= y)) {

                xi = poly.getVertex(i).lng();
                xj = poly.getVertex(j).lng();

                if ((xi + (xj - xi) * (y - yi) / (yj - yi)) < x) {
                    oddNodes = !oddNodes;
                }
            }
        }

        return oddNodes;
    };

    /**
     * Custom control
     */
    var zoomAllControl = function (data) {

        var F = function () {};
        F.prototype = new GControl();

        F.prototype.initialize = function(map) {
            var container = document.createElement("div");
            var zoomAllDiv = document.createElement("div");
            this.setButtonStyle_(zoomAllDiv);
            container.appendChild(zoomAllDiv);
            zoomAllDiv.appendChild(document.createTextNode("Show nearest spots"));
            GEvent.addDomListener(zoomAllDiv, "click", function() {
                var i, bounds, zoom;
                if (data.length > 1) {
                    bounds = new GLatLngBounds();
                    for (i = 0; i < data.length; i++) {
                        bounds.extend(new GLatLng(data[i].lat, data[i].lng));
                    }
                    zoom = map.getBoundsZoomLevel(bounds);
                    map.setZoom(zoom - 1);
                }
            });

            map.getContainer().appendChild(container);
            return container;
        }

        F.prototype.getDefaultPosition = function() {
            return new GControlPosition(G_ANCHOR_TOP_RIGHT, new GSize(7, 7));
        }

        // Sets the proper CSS for the given button element.
        F.prototype.setButtonStyle_ = function(button) {
            button.style.color = "black";
            button.style.backgroundColor = "white";
            button.style.font = "11px Arial";
            button.style.border = "1px solid black";
            button.style.padding = "2px";
            button.style.textAlign = "center";
            button.style.width = "10em";
            button.style.cursor = "pointer";
            button.style.whiteSpace = "nowrap";
        }

        return new F();
    };





    TRAVEL.DestinationMap = function (target) {

        var self = this;
        var root = target;

        var map = null;

        var drawMap = function (map, model) {

            var i, j;
            var border, bordersCount, coordsCount;
            var polygonArray, polygon;
            var spots;

            map.setCenter(new GLatLng(model.lat, model.lng), model.zoom);

            // add borders
            if (model.borders) {
                for (i = 0, bordersCount = model.borders.length; i < bordersCount; i++) {
                    polygonArray = [];
                    border = model.borders[i];

                    for (j = 0, coordsCount = border.coordinates.length; j < coordsCount; j++) {
                        polygonArray.push(new GLatLng(border.coordinates[j].lat, border.coordinates[j].lng));
                    }

                    if (coordsCount > 0) {
                        polygonArray.push(new GLatLng(border.coordinates[0].lat, border.coordinates[0].lng));
                    }

                    polygon = new GPolygon(polygonArray, "#000000", 1, 1, "#000000", 0.0);
                    border.polygon = polygon;

                    // TODO: XN-114
                    // map.addOverlay(polygon);

                    (function(index) {
                        GEvent.addListener(polygon, "click", function(overlay, point) {
                            self.notify("onRegionClick", model.borders[index].link);
                        });
                    })(i);
                }

                if (model.borders.length > 1) {
                    GEvent.addListener(map, "mousemove", function(p) {
                        var i;

                        for (i = 0; i < model.borders.length; i++) {
                            if (contains(model.borders[i].polygon, p)) {
                                self.notify("onRegionMoveIn", model.borders[i].name);
                                return;
                            }
                        }

                        self.notify("onRegionMoveOut");
                    });
                }
            }

            spots = model.sweetspots;

            // add spots
            if (spots && spots.length > 0 && false) {

                // Create a base icon for all of our markers that specifies the
                // shadow, icon dimensions, etc.
                var baseIcon = new GIcon(G_DEFAULT_ICON);
                baseIcon.iconSize = new GSize(11, 11);
                baseIcon.iconAnchor = new GPoint(5, 5);
                baseIcon.infoWindowAnchor = new GPoint(9, 2);
                baseIcon.image = baseUrl + 'new-i/markers/circle.png';
                baseIcon.shadow = '';

                for (i = 0; i < spots.length; i++) {
                    (function (s) {
                        var icon = new GIcon(baseIcon);
                        icon.image = s.icon || icon.image;

                        if (Math.abs(model.lat - s.lat) < 1e-5 && Math.abs(model.lng - s.lng) < 1e-5) {
                            icon.iconSize = new GSize(22, 22);
                            icon.iconAnchor = new GPoint(11, 11);
                            icon.infoWindowAnchor = new GPoint(20, 2);
                        }

                        var marker = new GMarker(new GLatLng(s.lat, s.lng), icon);
                        map.addOverlay(marker);

                        if (s.title) {
                            GEvent.addListener(marker, "click", function() {
                                var div = document.createElement('div');
                                div.className = 'map-bubble';
                                
                                $(div).append(['<h1><a href="', s.link, '">', s.title, '</a></h1>',
                                        TRAVEL.para(s.info).replace(ampPattern, '&')].join(''));
                                                                
                                marker.openInfoWindowHtml(div, {'maxWidth': 200});
                            });
                        }
                    })(spots[i]);

                    map.addControl(zoomAllControl(spots));
                }

            }

        };
        

        this.isShown = function() {
            return !!map;
        };

        this.create = function(model) {
            try {
                if (!map) {
                    if (typeof google === "undefined") {
                        TRAVEL.MapLoader.attachObserver('mapLoaded', function () {
                            map = new GMap2(root);
                            map.addControl(new GSmallMapControl());
                            // map.disableDragging();
                            document.getElementsByTagName("body")[0].onunload = function() { GUnload(); };
                            drawMap(map, model);
                        });
                        TRAVEL.MapLoader.init();
                    }
                } else {
                    drawMap(map, model);
                }
            } catch (exc) {}
        };

        TRAVEL.Observable2(this);
    };
})();


/**
 * @singleton
 */
TRAVEL.MapLoader = (function () {

    var self = TRAVEL.Observable2();

    self.init = function () {
        var script = document.createElement("script");
        script.src = TRAVEL.mapLink + '&callback=TRAVEL.MapLoader.loaded';
        script.type = "text/javascript";
        document.getElementsByTagName("head")[0].appendChild(script);
    };

    self.loaded = function () {
        google.load('maps', '2', {
            'callback': function () {
                self.notify('mapLoaded');
            },
            'language': TRAVEL.language || 'en'
        });
    };

    return self;
})();
