﻿var mouseX;
var mouseY;
var navigationLevel = 'Continent';
var countryLevelZoom = 3;
var continentLevelZoom = 1;
var gisObjects = [];
var tooltipEnabled = true;
var markers = [];
var markersInClaster = [];
var osmMapType = null;
var northAmericaClicked = false;
var infoWindowOpened = false;
var tipText = null;
var me = null;
var infoWindow = null;
var countryCustomZoom = -1;
var clickOnMarker = false;
var selectedContinentId = -1;
var contentObjectType = "hotel";
var infoBubbleMaxWidth = 600;
var infoBubbleMaxHeight = 400;
var infoWindowAutoCloseInterval = 3000;
var infoWindowAutoCloseTimeoutId;
var currentInfoWindow;
var currentInfoWindowMarker;
var singleObjectMaxZoom = 14;

function Mapper() {
    me = this;
    this.markerClusterer = null;

    this.init = function () {
        showTooltip(0, 0, null);
        var myLatlng = new window.google.maps.LatLng(0, 0);
        var myOptions = {
            zoom: 1,
            center: myLatlng,
            mapTypeId: window.google.maps.MapTypeId.TERRAIN,
            scrollwheel: false,
            draggable: false,
            mapTypeControl: false,
            disableDoubleClickZoom: true
        };
        var mapdiv = document.getElementById("mapdiv");
        if (mapdiv == null) {
            return;
        }
        this.map = new window.google.maps.Map(mapdiv, myOptions);
        this.clearMap();

        this.getObjects("GetContinents");
        this.createMapButton();

        window.google.maps.event.addListener(this.map, 'mousemove', me.OnMouseMove);
        window.google.maps.event.addListener(this.map, 'click', me.OnMouseClick);

        document.onmousemove = this.documentOnMouseMove;

        infoWindow = new InfoBubble({
            map: me.map,
            position: new window.google.maps.LatLng(-70, 0),
            maxWidth: infoBubbleMaxWidth,
            maxHeight: infoBubbleMaxHeight,
            shadowStyle: 1,
            padding: 10,
            borderRadius: 4,
            arrowSize: 0,
            borderWidth: 1,
            disableAutoPan: true,
            backgroundClassName: 'phoney'
        });
        window.google.maps.event.addListener(infoWindow, 'closeclick', processCloseClick);
        // Почему-то в некоторых случаях zoom карты внезапно становился максимальным.
        // Например, в случае отображения одного отеля из его карточки.
        // Введено ограничение.
        window.google.maps.event.addListener(me.map, 'zoom_changed', function () {
            if (me.map.getZoom() > 18) {
                me.map.setZoom(10);
            }
        });
    };

    this.documentOnMouseMove = function (evt) {
        var e = (window.event) ? window.event : evt;

        try {
            mouseX = e.clientX + (document.documentElement.scrollLeft || document.body.scrollLeft) - document.documentElement.clientLeft;
            mouseY = e.clientY + (document.documentElement.scrollTop || document.body.scrollTop) - document.documentElement.clientTop;

            var pmap = document.getElementById('mapdiv');
            var x = pmap.offsetLeft;
            var y = pmap.offsetTop;
            var w = pmap.offsetWidth;
            var h = pmap.offsetHeight;

            for (var parent = pmap.offsetParent; parent; parent = parent.offsetParent) {
                x += parent.offsetLeft;
                y += parent.offsetTop;
            }

            var px = mouseX - x;
            var py = mouseY - y;
            var bounds = me.map.getBounds();

            var cx = bounds.getCenter().lng();
            var l = bounds.getSouthWest().lng();
            var r = bounds.getNorthEast().lng();
            if (cx > r) r = 180;
            if (cx < l) l = -179;

            var insideMap = 1;
            if (px < 0 || py < 0 || px > w || py > h) insideMap = 0;
            if (mapLng > 0 && mapLng > l && mapLng > cx && px < w / 2) insideMap = 0;
            if (mapLng < 0 && mapLng < r && mapLng < cx && px > w / 2) insideMap = 0;
            if (insideMap == 1) {
                showTooltip(mouseX, mouseY, tipText);
                if (hilightedShape != null) {
                    pmap.style.cursor = 'hand';
                } else {
                    pmap.style.cursor = 'default';
                }
            } else {
                showTooltip(mouseX, mouseY, null);
            }
        } catch (ex) { }
    };

    this.clearMap = function () {
        var i;
        for (i = 0; i < gisObjects.length; i++) {
            if (gisObjects[i].shape != null) {
                gisObjects[i].shape.setMap(null);
            }
        }
        gisObjects = [];
        for (i = 0; i < markers.length; i++) {
            window.google.maps.event.clearInstanceListeners(markers[i]);
            markers[i].setMap(null);
        }
        markers = [];
        for (i = 0; i < markersInClaster.length; i++) {
            window.google.maps.event.clearInstanceListeners(markersInClaster[i]);
            markersInClaster[i].setMap(null);
        }
        markersInClaster = [];
        if (me.map.overlayMapTypes.length == 1) {
            me.map.overlayMapTypes.removeAt(0);
            osmMapType = null;
        }
        if (me.markerClusterer != null) {
            me.markerClusterer.clearMarkers();
            me.markerClusterer = null;
        }
        if (hilightedShape != null) {
            hilightedShape.setMap(null);
        }
    };

    /*
    this.getContentStringFromGisObjectOLD = function (gisObject) {
    try {
    var link = gisObject.marker_info[4];
    if (link == null) {
    link = "";
    }
    if (link.substring(0, 7) != "http://") {
    link = "http://" + link;
    }
    if (link.substring(link.length - 1) == "/") {
    link = link.substring(0, link.length - 1);
    }
    var image = gisObject.marker_info[5];
    var result = '<div id="content' + gisObject.id + '" class="map-info" style="border-color:#fff; vertical-align:middle; cursor:default">' +
    '<table style="border: 0;">' +
    '<tr style="border: 0;">' +
    '<td style="border: 0;">' + '<h1><img width="200" height="100" src="' + image + '"></h1>' + '</td>' +
    '<td style="border: 0;">' + '<h1>' + gisObject.name + '</h1>' + '<br>' +
    gisObject.parent + '<br>' +
    'Стоимость от ' + gisObject.marker_info[2] + ' до ' + '' + gisObject.marker_info[3] + '<br>' +
    '<p><a href="' + link + '">' + link.substring(7) + '</a></p>' +
    '</td>' +
    '</tr>' +
    '</table>' + '</div>';
    return result;
    } catch (e) {
    return null;
    }
    };
    */

    var getSingleDayPostfix = function (digit) {
        switch (digit) {
            case "0": return "дней";
            case "1": return "день";
            case "2": return "дня";
            case "3": return "дня";
            case "4": return "дня";
            case "5": return "дней";
            case "6": return "дней";
            case "7": return "дней";
            case "8": return "дней";
            case "9": return "дней";
            default: return "";
        }
    }

    var getTravelDurationDaysString = function (duration) {
        if (duration.length > 1) {
            var lastTwoDecimals = duration.substr(duration.length - 2, 2);
            if (lastTwoDecimals == "11" || lastTwoDecimals == "12" || lastTwoDecimals == "13" || lastTwoDecimals == "14")
                return "дней";
            else
                return getSingleDayPostfix(lastTwoDecimals.substr(lastTwoDecimals.length - 1, 1));
        }
        else {
            return getSingleDayPostfix(duration);
        }
    }

    this.getContentStringFromGisObject = function (gisObject) {
        var contentString = "";
        var link = gisObject.marker_info[4];
        if (link == null) {
            link = "";
        }
        if (link.substring(0, 7) != "http://") {
            link = "http://" + link;
        }
        if (link.substring(link.length - 1) == "/") {
            link = link.substring(0, link.length - 1);
        }
        var image = gisObject.marker_info[5];
        //contentString += '<div >';
        contentString += '<div class="block_hotel">';
        contentString += '<div class="otel_foto_border">';
        contentString += '<a href="#"> <img src="/ImageGen/200' + image + '" width="200" height="152" alt="" /></a>';
        contentString += '</div>';

        contentString += '<div class="block_hotel_right">';
        contentString += '<div class="block_hotel_atrib">';
        contentString += '<div class="name"> <a href="/NavigateToCatalogItem.ashx?id=' + gisObject.id + '">' + gisObject.name + '</a></div>';
        contentString += '<div class="place">' + gisObject.parent + '</div>';
        contentString += '<a class="site" href="' + link + '">' + link.substring(7) + '</a>';
        if ((gisObject.contentObjectType == "hotel") || (gisObject.contentObjectType == "travel")) {
            contentString += '<div class="price_text">цена от</div>';
            contentString += '<div class="price">' + gisObject.currencySign + " " + gisObject.marker_info[2] + '</div>';
            if (gisObject.contentObjectType == "hotel") {
                contentString += '<div class="price_text2">за ночь</div>';
            }
            else if (gisObject.contentObjectType == "travel") {
                contentString += '<div class="price_text2">за ' + gisObject.travelDuration + ' ' + getTravelDurationDaysString(gisObject.travelDuration) + '</div>';
            }
        }
        contentString += '</div>';
        
        if ((gisObject.contentObjectType == "hotel") || (gisObject.contentObjectType == "place")) {
            contentString += '<div class="block_hotel_rait">';
            contentString += '  <div class="title">РЕЙТИНГ NILSEN</div>';
            var arr = ["unactive", "unactive", "unactive", "unactive"];
            for (var j = 0; j < 3; j++) {
                if (gisObject.raiting > j) {
                    arr[j] = "active";
                }
                contentString += '      <div class="' + arr[j] + '"></div>';
            }
            contentString += '      <div class="clear"> </div>';
            contentString += '  </div>';
        }
        contentString += '</div>';
        contentString += '	        <div class="clear"> </div>';
        contentString += '	        <div class="about"><span>' + gisObject.mainDescription + '</span>';
        contentString += '&nbsp;<span class="detail"><a href="/NavigateToCatalogItem.ashx?id=' + gisObject.id + '">Подробнее...</a></span>';
        contentString += '</div>';

        contentString += '</div>';
        return contentString;
    };

    this.getContentStringFromGisObjects = function (gisObjects) {
        var contentString = "";
        for (var i = 0; i < gisObjects.length; i++) {
            contentString += me.getContentStringFromGisObject(gisObjects[i]);
        }
        return contentString;
    };

    this.geoMarkerClick = function (data) {
        clickOnMarker = false;
        if (infoWindowOpened) {
            return;
        }
        showTooltip(0, 0, null);
        var jsonData = eval('(' + data + ')');
        if (jsonData.gis_objects.length == 0) {
            return;
        }

        infoWindow = new InfoBubble({
            map: me.map,
            position: new window.google.maps.LatLng(-70, 0),
            maxWidth: infoBubbleMaxWidth,
            maxHeight: infoBubbleMaxHeight,
            shadowStyle: 1,
            padding: 10,
            arrowSize: 0,
            borderWidth: 2,
            borderRadius: 4,
            disableAutoPan: true,
            backgroundClassName: 'phoney'
        });
        infoWindow.setContent(me.getContentStringFromGisObjects(jsonData.gis_objects));
        var center = me.map.getCenter();
        var lng = center.lng();
        var mapBounds = me.map.getBounds();
        var sw = mapBounds.getSouthWest();
        var ne = mapBounds.getNorthEast();
        var lat = ne.lat() - (ne.lat() - sw.lat()) * 0.95;
        var pos = new window.google.maps.LatLng(lat, lng);
        infoWindow.setPosition(pos);
        showTooltip(0, 0, null);
        openInfoWindow(infoWindow);
        infoWindowOpened = true;
        window.google.maps.event.addListener(infoWindow, 'closeclick', processCloseClick);
        document.body.style.cursor = 'default';
    };

    // Метод для определения, нужно показывать маркер на геообъекте или нет.
    // Нужен для того, чтобы не отображать маркер для очень маленьких стран (Лихтенштейн, Монако и т.д.)
    // Вычисляется очень просто - площадь геообъекта меньше какого-то принятого значения (можно порегулировать, посмотреть).
    this.isSenceForShowMarker = function (polygons) {
        for (var i = 0; i < polygons.length; i++) {
            var polygon = polygons[i];
            var bounds = polygon.getBounds();
            var sw = bounds.getSouthWest();
            var ne = bounds.getNorthEast();
            var s = (ne.lng() - sw.lng()) * (ne.lat() - sw.lat());
            if (s > 2) {
                return true;
            }
        }
        return false;
    };

    this.onClusterIconMouseMove = function (pos, cluster) {
        clearTimeout(infoWindowAutoCloseTimeoutId);
        if (cluster != currentInfoWindowMarker) {
            closeCurrentInfoWindow();
            showTooltip(0, 0, null);
            var gisOobjects = [];
            for (var i = 0; i < cluster.markers_.length; i++) {
                gisOobjects.push(cluster.markers_[i].gisObject);
            }
            infoWindow = new InfoBubble({
                map: me.map,
                position: new window.google.maps.LatLng(-70, 0),
                maxWidth: infoBubbleMaxWidth,
                maxHeight: infoBubbleMaxHeight,
                shadowStyle: 1,
                padding: 10,
                arrowSize: 5,
                borderWidth: 1,
                borderRadius: 4,
                disableAutoPan: false,
                backgroundClassName: 'phoney'
            });

            infoWindow.setContent(me.getContentStringFromGisObjects(gisOobjects));
            infoWindow.setPosition(pos);
            infoWindowOpened = true;
            window.google.maps.event.addListener(infoWindow, 'closeclick', processCloseClick);

            currentInfoWindowMarker = cluster;
            openInfoWindow(infoWindow);
        }
    };

    this.onClusterIconMouseOut = function (pos, cluster) {
        clearTimeout(infoWindowAutoCloseTimeoutId);
        infoWindowAutoCloseTimeoutId = setTimeout(processInfoWindowCloseTimeout, infoWindowAutoCloseInterval);
    }

    var openInfoWindow = function (infoWindow, map, object, marker) {
        currentInfoWindow = infoWindow;
        infoWindow.open(map, object);
        infoWindowOpened = true;

        if (marker != undefined) {
            currentInfoWindowMarker = marker;
            attachInfoWindowSourceMarker(marker, true);
        }

        window.google.maps.event.addListener(infoWindow, 'closemove', function () {
            clearTimeout(infoWindowAutoCloseTimeoutId);
        });
        $("div.phoney", infoWindow.bubble_).parents().filter(":first").bind("mouseover", function () {
            clearTimeout(infoWindowAutoCloseTimeoutId);
        });
        $("div.phoney", infoWindow.bubble_).parents().filter(":first").bind("mouseout", function () {
            clearTimeout(infoWindowAutoCloseTimeoutId);
            infoWindowAutoCloseTimeoutId = setTimeout(function () {
                processInfoWindowCloseTimeout();
                unbindInfoWindow();
            }, infoWindowAutoCloseInterval)
        });
    }

    var closeCurrentInfoWindow = function () {
        if (currentInfoWindow != null)
            currentInfoWindow.close();
        infoWindowOpened = false;
    }

    var processCloseClick = function () {
        clearTimeout(infoWindowAutoCloseTimeoutId);
        currentInfoWindowMarker = null;
        infoWindowOpened = false;
    }

    var attachInfoWindowSourceMarker = function (marker, isDetach) {
        var mouseMoveHandle = window.google.maps.event.addListener(marker, 'mousemove', function () {
            if (marker == currentInfoWindowMarker)
                clearTimeout(infoWindowAutoCloseTimeoutId);
        });
        var mouseOutHandle = window.google.maps.event.addListener(marker, 'mouseout', function () {
            clearTimeout(infoWindowAutoCloseTimeoutId);
            infoWindowAutoCloseTimeoutId = setTimeout(function () {
                processInfoWindowCloseTimeout();
                if (isDetach)
                    removeListenersFromMarker(mouseMoveHandle, mouseOutHandle);
            }, infoWindowAutoCloseInterval)
        });
    }

    var processInfoWindowCloseTimeout = function () {
        closeCurrentInfoWindow();
        clearTimeout(infoWindowAutoCloseTimeoutId);
        currentInfoWindowMarker = null;
    }

    var unbindInfoWindow = function () {
        $(this).unbind('mousemove mouseout closemove');
        $(currentInfoWindow).unbind('closemove');
    }

    var removeListenersFromMarker = function (mouseMoveHandle, mouseOutHandle) {
        window.google.maps.event.removeListener(mouseMoveHandle);
        window.google.maps.event.removeListener(mouseOutHandle);
    }

    this.showGisObjects = function (data) {

        var gStyles = [{
            url: '/images/map/' + contentObjectType + '35.png',
            height: 35,
            width: 35,
            anchor: [12, 10],
            textColor: '#fff',
            textSize: 10
        }, {
            url: '/images/map/' + contentObjectType + '45.png',
            height: 45,
            width: 45,
            anchor: [18, 12],
            textColor: '#fff',
            textSize: 10
        }, {
            url: '/images/map/' + contentObjectType + '55.png',
            height: 55,
            width: 55,
            anchor: [24, 14],
            textColor: '#fff',
            textSize: 10
        }];

        me.clearMap();

        if (data == "") {
            return;
        }

        var jsonData = eval('(' + data + ')');
        try {

            if (jsonData.ShowBackground) {
                /* Пробы с размещением на фоне целой карты мира или даже разбитой на четыре части. Ничего хорошего из этого не вышло.
                var ne1 = new window.google.maps.LatLng(80, 160);
                var sw1 = new window.google.maps.LatLng(-80, -160);
                var b1 = new window.google.maps.LatLngBounds(sw1, ne1);
                var gisObject1 = new GroundOverlay(b1, "/images/map/world_1_o.png", me.map);
                gisObjects.push(gisObject1);
                

                var ne1 = new window.google.maps.LatLng(80, 0);
                var sw1 = new window.google.maps.LatLng(0, -170);
                var b1 = new window.google.maps.LatLngBounds(sw1, ne1);
                var gisObject1 = new GroundOverlay(b1, "/images/map/world_nw.png", me.map);
                gisObjects.push(gisObject1);

                var ne2 = new window.google.maps.LatLng(0, 0);
                var sw2 = new window.google.maps.LatLng(-80, -170);
                var b2 = new window.google.maps.LatLngBounds(sw2, ne2);
                var gisObject2 = new GroundOverlay(b2, "/images/map/world_sw.png", me.map);
                gisObjects.push(gisObject2);

                var ne3 = new window.google.maps.LatLng(80, 170);
                var sw3 = new window.google.maps.LatLng(0, 0);
                var b3 = new window.google.maps.LatLngBounds(sw3, ne3);
                var gisObject3 = new GroundOverlay(b3, "/images/map/world_ne.png", me.map);
                gisObjects.push(gisObject3);

                var ne4 = new window.google.maps.LatLng(0, 170);
                var sw4 = new window.google.maps.LatLng(-80, 0);
                var b4 = new window.google.maps.LatLngBounds(sw4, ne4);
                var gisObject4 = new GroundOverlay(b4, "/images/map/world_se.png", me.map);
                gisObjects.push(gisObject4);
                */
                osmMapType = new window.google.maps.ImageMapType({
                    getTileUrl: function (coord) {
                        return "/media/32549/bkg2.png";
                    },
                    tileSize: new window.google.maps.Size(500, 500),
                    isPng: true,
                    alt: "OpenStreetMap layer",
                    name: "OpenStreetMap",
                    opacity: 1.0
                });
                me.map.overlayMapTypes.insertAt(0, osmMapType);
            }

            var i;

            for (i = 0; i < jsonData.gis_objects.length; i++) {
                var gisObject = jsonData.gis_objects[i];
                var showImage = true;

                if (gisObject.image_normal == undefined || gisObject.image_normal == 'null') {
                    gisObject.image_normal = null;
                }
                if (gisObject.image_hilighted == undefined || gisObject.image_hilighted == 'null') {
                    gisObject.image_hilighted = null;
                }

                if (gisObject.has_images == 0) showImage = false;
                if (gisObject.image_normal == null) showImage = false;
                if (gisObject.image_normal == undefined) showImage = false;
                if (gisObject.has_tiles == 1) showImage = false;

                if (gisObject.EastBound == 180) {
                    gisObject.EastBound = 179.999;
                }
                if (gisObject.WestBound == 180) {
                    gisObject.WestBound = 179.999;
                }

                var ne = new window.google.maps.LatLng(gisObject.NorthBound, gisObject.EastBound);
                var sw = new window.google.maps.LatLng(gisObject.SouthBound, gisObject.WestBound);
                var bnds = new window.google.maps.LatLngBounds(sw, ne);
                gisObject.bounds = bnds;

                if (showImage) {
                    var gisObjectImage = gisObject.image_normal;
                    gisObject.shape = new GroundOverlay(bnds, gisObjectImage, me.map);
                }

                if (gisObject.has_polygons) {
                    if (gisObject.polygons != null) {
                        var polygonSet = [];
                        for (var pi = 0; pi < gisObject.polygons.length; pi++) {
                            var points = [];
                            for (var j = 0; j < gisObject.polygons[pi].coordinates.length; j++) {
                                points.push(new window.google.maps.LatLng(gisObject.polygons[pi].coordinates[j][0], gisObject.polygons[pi].coordinates[j][1]));
                            }
                            var apolygon = new window.google.maps.Polygon({ paths: points }); //, strokeColor: "#f0be50", strokeOpacity: w, strokeWeight: 0.5, fillColor: "#be5000", fillOpacity: 0.5 });
                            polygonSet.push(apolygon);
                        }
                        gisObject.polygons = polygonSet;

                        if ((gisObject.polygons.length != 0) && (me.isSenceForShowMarker(polygonSet))
                        // следующая строка - запрет на отображение НУЛЕВЫХ маркеров
                        && (gisObject.ContentObjectCount > 0)
                            ) {

                            var gisObjectLatlng = polygonSet[0].getBounds().getCenter();
                            if ((gisObject.Latitude != null) && (gisObject.Longitude != null)) {
                                gisObjectLatlng = new window.google.maps.LatLng(gisObject.Latitude, gisObject.Longitude);
                            }
                            var title = gisObject.ContentObjectCount.toString();

                            var m_cont = '';
                            if (jsonData.level != 'Continent' && jsonData.level != 'Country' && jsonData.level != 'Region') {
                                m_cont = '<div class="marker"><img src="/images/map/' + contentObjectType + '35.png"/><span>' + title + '</span></div>';
                            }

                            var gisObjectMarker = new RichMarker({
                                position: gisObjectLatlng,
                                map: me.map,
                                draggable: false,
                                content: m_cont,
                                shadow: false
                            });

                            gisObjectMarker.gisObject = gisObject;
                            markers.push(gisObjectMarker);
                            attachInfoWindowSourceMarker(gisObjectMarker, false);
                            window.google.maps.event.addListener(gisObjectMarker, 'click', function () {
                                clickOnMarker = true;
                                var mark = this;
                                var containerObject = mark.gisObject;
                                var getString = null;
                                if (containerObject.type_name == "Continent") {
                                    getString = "ct=" + containerObject.Id.toString();
                                } else if (containerObject.type_name == "Country") {
                                    getString = "cr=" + containerObject.Id.toString();
                                } else if (containerObject.type_name == "Region") {
                                    getString = "rg=" + containerObject.Id.toString();
                                }

                                if (getString == null) {
                                    return;
                                }

                                document.body.style.cursor = 'wait';

                                $.ajax({
                                    type: "POST",
                                    url: "/geo.ashx?contentObjectType=" + contentObjectType + "&" + getString,
                                    success: me.geoMarkerClick,
                                    error: function () {
                                        clickOnMarker = false;
                                        document.body.style.cursor = 'default';
                                    }
                                });
                            });
                        }
                    }
                }

                if (jsonData.level == "ContentObject") {
                    if (gisObject.is_marker == 1) {
                        var hotelMarkerLatlng = new window.google.maps.LatLng(gisObject.central_lat, gisObject.central_lng);
                        var sRaitingForImage = "";
                        if (gisObject.contentObjectType == "hotel") {
                            sRaitingForImage = gisObject.raiting.toString();
                        }
                        var mImage = new window.google.maps.MarkerImage("/images/map/" + sRaitingForImage + gisObject.contentObjectType + ".png");
                        var marker = new window.google.maps.Marker({
                            position: hotelMarkerLatlng,
                            map: me.map,
                            title: gisObject.name,
                            icon: mImage
                        });
                        var contentString = me.getContentStringFromGisObject(gisObject);
                        marker.gisObject = gisObject;
                        marker.contentString = contentString;
                        markers.push(marker);
                        if (contentObjectType == gisObject.contentObjectType) {
                            markersInClaster.push(marker);
                        }
                        window.google.maps.event.addListener(marker, 'mousemove', function () {
                            if (this == currentInfoWindowMarker)
                                return;
                            closeCurrentInfoWindow();
                            infoWindow = new InfoBubble({
                                map: me.map,
                                position: this.position,
                                maxWidth: infoBubbleMaxWidth,
                                maxHeight: infoBubbleMaxHeight,
                                shadowStyle: 1,
                                padding: 10,
                                arrowSize: 5,
                                borderWidth: 1,
                                borderRadius: 4,
                                disableAutoPan: false,
                                backgroundClassName: 'phoney'
                            });

                            infoWindow.setContent(this.contentString);

                            openInfoWindow(infoWindow, me.map, this, this);
                            infoWindowOpened = true;
                            window.google.maps.event.addListener(infoWindow, 'closeclick', processCloseClick);

                        });
                    }
                }
                gisObjects.push(gisObject);
            }
            if (jsonData.level == "ContentObject") {
                me.markerClusterer = new window.MarkerClusterer(me.map, markersInClaster, {
                    maxZoom: 13,
                    gridSize: 50,
                    zoomOnClick: false,
                    styles: gStyles
                });
            }

            navigationLevel = jsonData.level;

            var zoom = -1;
            if (navigationLevel == "Continent") {
                zoom = continentLevelZoom;
            } else if (navigationLevel == "Country") {
                zoom = countryLevelZoom;
            } else if (navigationLevel == "ContentObject") {
                zoom = 5;
            }

            if ((jsonData.zoom != undefined) && (jsonData.zoom != -1)) {
                zoom = jsonData.zoom;
            }

            if (northAmericaClicked) {
                zoom = 2;
                northAmericaClicked = false;
            }

            if (countryCustomZoom != -1) {
                zoom = countryCustomZoom;
                countryCustomZoom = -1;
            }

            if ((zoom != undefined) && (zoom != -1)) {
                //try {
                me.map.setZoom(zoom);
                //} catch (e) {}
            }
            if (navigationLevel == "ContentObject") {
                var bounds = new window.google.maps.LatLngBounds();
                for (i = 0; i < gisObjects.length; i++) {
                    var myLatlng = new window.google.maps.LatLng(gisObjects[i].central_lat, gisObjects[i].central_lng);
                    bounds.extend(myLatlng);
                }

                if (gisObjects.length != 0) {
                    me.map.fitBounds(bounds);
                    if (gisObjects.length == 1) {
                        me.map.setZoom(singleObjectMaxZoom);
                    }
                }
                // Если мы отображаем один отель на карте, то fitBounds() вычисляет масштаб, равным 21 (максимальный)
                // Было принято решение пока в таком случаепринудительно ставить масштаб равный 10.
                if (me.map.getZoom() > 18) {
                    me.map.setZoom(10);
                }
            }

            updateMapControls(false);

        } catch (e) { ; }
    };

    this.getObjects = function (type, containerId) {
        var search = "?";
        if (window.location.search != "?m=1") {
            search = window.location.search;
        }
        var url = "/geo.ashx" + search + "&contentObjectType=" + contentObjectType + "&action=" + type;
        if (containerId != undefined) {
            url += "&id=" + containerId;
        }
        $.ajax({
            type: "GET",
            url: url,
            success: function (data) {
                me.showGisObjects(data);
            },
            error: function () {
                me.clearMap();
            }
        });
    };

    // ================================================================
    function showTooltip(x, y, tipText) {
        try {
            if (!tooltipEnabled) { return; }
            x += 2;
            y -= 28;
            var tt = document.getElementById('Tooltip');
            if (tt != null) {
                if (tipText == null) {
                    tt.style.visibility = 'hidden';
                } else {
                    var ttt = document.getElementById('Tooltip.text');
                    ttt.innerHTML = tipText;
                    try {
                        tt.style.left = x + 'px';
                        tt.style.top = y + 'px';
                    } catch (e1) { ; }
                    tt.style.visibility = 'visible';
                }
            }
        } catch (e) { ; }
    };


    // ================================================================
    // gisObjectIndexFromPoint
    // ================================================================
    function gisObjectIndexFromPoint(p) {
        for (var i = 0; i < gisObjects.length; i++) {
            var gisObject = gisObjects[i];
            if (gisObject != null) {
                if (gisObject.has_polygons == 1 && gisObject.polygons != undefined && gisObject.polygons != null) {
                    //var bnds = new GLatLngBounds();
                    //bnds.extend(new GLatLng(gisObject.bounds[0], gisObject.bounds[1]));
                    //bnds.extend(new GLatLng(gisObject.bounds[2], gisObject.bounds[3]));
                    //gisObject.bounds = bnds;
                    var bnds = gisObject.bounds;
                    if (bnds.contains(p)) {
                        for (var pi = 0; pi < gisObject.polygons.length; pi++) {
                            if (gisObject.polygons[pi].Contains(p)) {
                                return i;
                            }
                        }
                    }
                }
            }
        }
        return -1;
    }
    // ================================================================

    var hilightedObjectIndex = -2;
    var hilightedShape = null;
    var mapLng;
    // ================================================================
    this.OnMouseMove = function (p) {
        mapLng = p.latLng.lng();
        var sel = -1;
        sel = gisObjectIndexFromPoint(p.latLng);
        if (sel >= 0) {
            tipText = gisObjects[sel].caption;
            showTooltip(mouseX, mouseY, gisObjects[sel].caption);
        } else {
            showTooltip(mouseX, mouseY, null);
            tipText = null;
        }
        if (sel == hilightedObjectIndex) { return 0; }
        if (hilightedObjectIndex >= 0) {
            if (hilightedShape != null) {
                hilightedShape.setMap(null);
            }
            hilightedShape = null;
        }
        if (sel >= 0) {
            if (hilightedObjectIndex == -2) {
            }
            if (sel >= 0) {
                hilightedObjectIndex = sel;
                if (gisObjects[sel].image_hilighted != null) {
                    hilightedShape = new GroundOverlay(gisObjects[sel].bounds, gisObjects[sel].image_hilighted, me.map);
                }
            }
            me.map.getDiv().style.cursor = 'hand';
        } else {
            hilightedObjectIndex = -1;
        }
        return -1;
    };
    // ================================================================

    // ================================================================
    this.OnMouseClick = function (/*overlay, */point) {
        if (clickOnMarker) {
            return;
        }
        var sel = gisObjectIndexFromPoint(point.latLng);
        if (sel >= 0) {
            if (gisObjects[sel].on_click == 'zoom_next') {
                //customCountryZoomLevel = -1;
                var gisObject = gisObjects[sel];
                var objectName = gisObject.name;
                if (objectName == "North America") {
                    northAmericaClicked = true;
                }
                var typeName = gisObject.type_name;
                var zoom = gisObject.zoom_max + 1;
                var centerPoint = point;
                if (gisObject.has_polygons && gisObject.polygons != null && gisObject.polygons.length > 0) {
                    var bnds = new window.google.maps.LatLngBounds();
                    for (var i = 0; i < gisObject.polygons.length; i++) {
                        var pb = gisObject.polygons[i].getBounds();
                        //var pb = polyGetBounds(gisObject.polygons[i]);
                        bnds.extend(pb.getSouthWest());
                        bnds.extend(pb.getNorthEast());
                    }
                    //zoom = map.getBoundsZoomLevel(bnds);
                    centerPoint = bnds.getCenter();
                    //_this.map.fitBounds(bnds);
                }
                var caption = gisObject.caption;
                // Заклад на Россию для перехода с уровня континентов сразу на уровень регионов. Лучшего выхода не нашел.
                if (typeName == 'Continent') {
                    //zoom = countryLevelZoom;
                    if (caption == 'Россия') {
                        selectedContinentId = gisObject.Id;
                        typeName = 'Country';
                        caption = 'Россия';
                        navigationLevel = 'Country';
                        if (gisObject.Id == 30584) {
                            gisObject.Id = 30585;
                            gisObject.has_regions = 1;
                            gisObject.zoom = 2;
                        }
                    }
                }
                if (typeName == 'Continent') {
                    directionsManager.setDirection(gisObject.Id);
                    selectedContinentId = gisObject.Id;
                    me.getObjects("GetCountries", gisObject.Id);
                    document.getElementById('ButtonControlDiv').style.visibility = 'visible';
                    document.getElementById('ContinentsButton').style.visibility = 'visible';
                } else if (typeName == 'Country') {
                    directionsManager.setDirection(selectedContinentId, gisObject.Id);
                    if ((gisObject.has_regions != null) && (gisObject.has_regions != 0)) {
                        countryCustomZoom = gisObject.zoom;
                        me.getObjects("GetRegions", gisObject.Id);
                        document.getElementById('ButtonControlDiv').style.visibility = 'visible';
                        document.getElementById('CountriesButton').style.visibility = 'visible';
                        document.getElementById('ContinentsButton').style.visibility = 'visible';
                    } else {
                        me.getObjects("GetContentObjectByCountry", gisObject.Id);
                        document.getElementById('ButtonControlDiv').style.visibility = 'visible';
                        document.getElementById('CountriesButton').style.visibility = 'visible';
                        document.getElementById('ContinentsButton').style.visibility = 'visible';
                    }
                } else if (typeName == 'Region') {
                    directionsManager.setDirection(selectedContinentId, gisObject.parentId, gisObject.Id);
                    me.getObjects("GetContentObjectByRegion", gisObject.Id);
                    document.getElementById('ButtonControlDiv').style.visibility = 'visible';
                    document.getElementById('CountriesButton').style.visibility = 'visible';
                    document.getElementById('ContinentsButton').style.visibility = 'visible';
                }
                if (gisObject.central_lat != null && gisObject.central_lng != null) {
                    centerPoint = new window.google.maps.LatLng(gisObject.central_lat, gisObject.central_lng);
                }
                me.map.setCenter(centerPoint);
            }
        }
    };

    // ================================================================
    this.createMapButton = function () {
        var buttonControlDiv = document.createElement('DIV');
        buttonControlDiv.id = "ButtonControlDiv";
        buttonControlDiv.style.visibility = 'hidden';
        var buttonControl = new ButtonControl(buttonControlDiv, me.map, me);
        buttonControlDiv.index = 1;
        me.map.controls[window.google.maps.ControlPosition.TOP_LEFT].push(buttonControlDiv);
    };

    this.buttonCountriesClicked = function () {
        me.mapButtonClicked("CountriesButton");
    };

    this.buttonContinentsClicked = function () {
        me.mapButtonClicked("ContinentsButton");
    };

    // ================================================================
    this.mapButtonClicked = function (buttonName) {
        if (buttonName == 'ContinentsButton') {
            if (navigationLevel == 'Continent') return;
            navigationLevel = 'Continent';
            me.map.setCenter(new window.google.maps.LatLng(10, 0), 1);
            me.map.setZoom(continentLevelZoom);
            document.getElementById('ButtonControlDiv').style.visibility = 'hidden';
            document.getElementById('CountriesButton').style.visibility = 'hidden';
            document.getElementById('ContinentsButton').style.visibility = 'hidden';
            me.getObjects("GetContinents", selectedContinentId);
            directionsManager.reset();
            selectedContinentId = -1;
        }
        if (buttonName == 'CountriesButton') {
            if (navigationLevel == 'Country') return;
            navigationLevel = 'Country';
            me.map.setZoom(countryLevelZoom);
            document.getElementById('CountriesButton').style.visibility = 'hidden';
            me.getObjects("GetCountries", selectedContinentId);
            directionsManager.reset();
            directionsManager.setDirection(selectedContinentId);
        }
    };

    // ================================================================
    function updateMapControls() {
        me.map.mapTypeControl = false;
        me.map.panControl = false;
        me.map.streetViewControl = false;
        infoWindow.close();
        infoWindowOpened = false;
        me.map.setOptions({
            draggable: false,
            zoomControl: false
        });
        if (navigationLevel == 'Continent') {
            me.map.mapTypeControl = false;
            me.map.setOptions({
                scrollwheel: false,
                disableDoubleClickZoom: true
            });
        } else if (navigationLevel == 'Country') {
            me.map.setOptions({
                draggable: false,
                scrollwheel: false,
                disableDoubleClickZoom: true
            });
        } else if (navigationLevel == 'Region') {
            me.map.setOptions({
                scrollwheel: false,
                disableDoubleClickZoom: true
            });
        } else if (navigationLevel == 'ContentObject') {
            /*me.map.mapTypeControl = true;*/
            me.map.setOptions({
                draggable: true,
                scrollwheel: true,
                disableDoubleClickZoom: false,
                zoomControl: true
            });
        }
    }
}

$(function () { new Mapper().init(); });

