﻿var $j = jQuery;

function Page() {
    var debugEnabled = false;
    var panoramioEnabled = true;
    var polednicekEnabled = true;
    var polednicekBaseUrl = "http://www.polednicek.cz";
    var polednicekServiceUrl = polednicekBaseUrl + "/georss2.ashx";

    var img_root = "http://www.prazskecyklostezky.cz/Images/aicon/";
    var map = null;
    var pcPolylines = [];
    var cachedIcons = {};
    var visiblePois = {};
    var isFirstLoad = true;
    var panoramio_photo_size = 'small';
    var markerManager = null;

    // methods
    this.initialize = initialize;

    function initialize(cyclopathID, serviceUrl) {
        if (GBrowserIsCompatible()) {
            debug("initialize");
            map = new GMap2(document.getElementById("aMapa"));
			map.enableScrollWheelZoom();
            map.removeMapType(G_HYBRID_MAP);

            map.setCenter(new GLatLng(50.058975, 14.409764), 11);
            map.addControl(new GLargeMapControl());
            map.addControl(new GMapTypeControl());

            //markerManager = new MarkerManager(map);

            loadMap(cyclopathID, serviceUrl);
            GEvent.addListener(map, "moveend", function() {
                debug("moved");
                if (!isFirstLoad) {
                    loadMap(cyclopathID, serviceUrl);
                }
            });

            GEvent.addListener(map, "zoomend", function() {
                debug("zoomend");
                if (!isFirstLoad) {
                    map.closeInfoWindow();
                    map.clearOverlays();
                    visiblePois = {};
                    //                    //markerManager.clearMarkers();
                }
            });
        }
    };

    function loadMap(cyclopathID, serviceUrl) {
        //isFirstLoad = false;
        loadCyclopath(cyclopathID, serviceUrl);
        if (panoramioEnabled && map.getZoom() >= 15) {
            loadPanoramio();
        }
        if (polednicekEnabled && map.getZoom() >= 15) {
            loadPolednicek();
        }
    };

    function loadCyclopath(cyclopathID, serviceUrl) {
        // pro jaky mapovy vyrez chci nahrat znacky?
        var bounds = map.getBounds();
        var north = bounds.getNorthEast().lat();
        var east = bounds.getNorthEast().lng();
        var south = bounds.getSouthWest().lat();
        var west = bounds.getSouthWest().lng();

        var scale = getScale(map.getZoom());

        var serviceData;
        if (!cyclopathID) {
            serviceData = {
                'minX': south,
                'maxX': north,
                'minY': west,
                'maxY': east,
                'scale': scale,
                'action': 'getroutes'
            };
        } else {
            serviceData = {
                'minX': south,
                'maxX': north,
                'minY': west,
                'maxY': east,
                'scale': scale,
                'cyclopathID': cyclopathID,
                'action': 'getroutesbycyclopathid'
            };
        }

        // Show info bubble for 15 seconds; bubble will be closed on data loaded
        //map.showInfoBubble("Načítám data, čekejte prosím.", 15000 );

        // udelam JsonP request
        //serviceUrl = serviceUrl + "&callback=?";
        serviceUrl += '?callback=?';
        debug("loading cyclopath, serviceUrl=" + serviceUrl + ", scale=" + scale);
        $j.getJSON(serviceUrl, serviceData, function(data, textStatus) {
            onCyclopathLoaded(data, textStatus);
            debug("current zoom=" + map.getZoom());
        });
    };

    function getScale(zoom) {
        //        1:2250 = z17
        //        1:4500 = z16
        //        1:9000 = z15
        //        1:23000 = z14
        //        1:46000 = z13
        //        1:93000 = z12
        //        1:188000 = z11
        //        1:350000 = z10
        //        1:725000 = z9
        //        1:1500000 = z8
        var scale = 8000;

        switch (zoom) {
            case 0:
            case 1:
            case 2:
            case 3:
            case 4:
            case 5:
            case 6:
            case 7:
            case 8:
                scale = 1000000;
                break;
            case 9:
                scale = 500000;
                break;
            case 10:
            case 11:
                scale = 250000;
                break;
            case 12:
                scale = 125000;
                break;
            case 13:
                scale = 64000;
                break;
            case 14:
            case 15:
                scale = 32000;
                break;
            case 16:
                scale = 16000;
                break;
        }

        //debug("zoom=" + zoom + ", scale=" + scale);
        return scale;
    };

    function getZoom(scale) {
        //        1:2250 = z17
        //        1:4500 = z16
        //        1:9000 = z15
        //        1:23000 = z14
        //        1:46000 = z13
        //        1:93000 = z12
        //        1:188000 = z11
        //        1:350000 = z10
        //        1:725000 = z9
        //        1:1500000 = z8
        var zoom = 8;

        switch (scale) {
            case 500000:
                zoom = 9;
                break;
            case 450000:
                zoom = 10;
                break;
            case 250000:
                zoom = 11;
                break;
            case 125000:
                zoom = 12;
                break;
            case 64000:
                zoom = 13;
                break;
            case 32000:
                zoom = 14;
                break;
            case 16000:
                zoom = 16;
                break;
            case 8000:
                zoom = 17;
                break;
            case 4000:
                zoom = 18;
                break;
        }

        //debug("scale=" + scale + ", zoom=" + zoom);
        return zoom;
    };

    function onCyclopathLoaded(response, textStatus) {
        debug("onCyclopathLoaded, status=" + textStatus);

        // If response is invalid, exit
        if (!response || !response.sections || response.sections.length == 0) {
            debug('Failed to read response or response is empty');
            //map.closeInfoWindow();
            return;
        }

        // Remove all polylines                    
        removeAllPolylines();
        debug("old polylines removed");

        // Add polylines (cyclopath sections) to map
        for (var i = 0; i < response.sections.length; i++) {
            var routePoints = response.sections[i].points;
            // Do not add polylines with zero or one point - it freezes the map (amapy bug)
            if (routePoints.length <= 1)
                continue;

            var opacity = response.sections[i].opacity;
            var color = '#' + response.sections[i].color;
            var lineweight = response.sections[i].lw;
            var polyline = parsePolyline(routePoints, opacity, color, lineweight);
            pcPolylines.push(polyline);
            map.addOverlay(polyline);
        }

        debug("new polylines added");
        // If map is loaded for the first time set zoom to starting point
        if (isFirstLoad == true) {
            var zoom = getZoom(response.mapScale);
            debug("initial zoom to mapX=" + response.mapX + ", mapY=" + response.mapY + ", scale=" + response.mapScale + ", zoom=" + zoom);
            var bounds = polyline.getBounds();
            debug("bounds, zoomlevel=" + map.getBoundsZoomLevel(bounds));
            var mapCenterPoint = new GLatLng(response.mapX, response.mapY);
            map.setCenter(mapCenterPoint, zoom);
            isFirstLoad = false;
        }

        // Add POIs to map
        var markers = [];
        var visibles = visiblePois;
        var approved = {}; // latest added pois
        debug("adding POIs");
        for (var i = 0; i < response.pois.length; i++) {
            var poi = response.pois[i];
            if (!poi || !poi.icon)
                continue;

            approved[poi.id] = true;
            // if poi is visible, we do not insert it on the map
            if (visibles[poi.id]) continue;
            // create marker               
            var marker = getCyclopathMarker(poi);
            // add marker to collection
            markers.push(marker);
            visibles[poi.id] = marker;
            map.addOverlay(marker);
        }
        debug("POIs added");

        // remove markers that are not among latest added
        var toRemove = [];
        for (var id in visibles) {
            if (!approved[id] && isInteger(id)) {
                visibles[id].remove();
                toRemove.push(id);
            }
        }
        for (var i = 0; i < toRemove.length; i++) {
            delete visibles[toRemove[i]];
        }
        debug("invisible POIs removed");
    };

    function removeAllPolylines() {
        debug("removing polylines, count=" + pcPolylines.length);
        for (var i = 0; i < pcPolylines.length; i++) {
            map.removeOverlay(pcPolylines[i]);
        }
        pcPolylines = [];
    };

    function parsePolyline(data, opacity, color, lineweight) {
        var points = [];

        for (var i = 0; i < data.length; i++) {
            points.push(new GLatLng(data[i].x, data[i].y));
        }

        var polyline = new GPolyline(points, color, lineweight, opacity);
        return polyline;
    };

    function getCyclopathMarker(poi) {
        var icon = getIcon(img_root + poi.icon.src, poi.icon.w, poi.icon.h, poi.icon.offX, poi.icon.offY);
        var title = "";
        var marker = new GMarker(new GLatLng(poi.x, poi.y), { title: title, icon: icon, draggable: false, zIndexProcess: function getZ(marker, b) { return 100; } });

        //        var marker = new AMarker(pos, {
        //            'icon': aIcon,
        //            'checkVisibility': false,
        //            'clickable': true,
        //            'draggable': false,
        //            'toFrontOnHover': true
        //        });  

        if (poi.btext) {
            var text = "<div class='bubble-content'>" + poi.btext;
            if (poi.blink) {
                text += "<p><a href='" + poi.blink + "' class='bubble-link'>zobrazit stránku stezky</a></p>";
            }
            text += "</div>";

            GEvent.addListener(marker, 'click', function() {
                marker.openInfoWindowHtml(text, { maxWidth: 400 });
            });
        }

        return marker;
    };

    function isInteger(s) {
        if (s == "") return;
        for (i = 0; i < s.length; i++) {
            if ((s.charAt(i) < '0') || (s.charAt(i) > '9')) return false;
        }
        return true;
    };

    function fitMap(map, points) {
        if (points.length == 0) {
            return;
        }
        var bounds = new GLatLngBounds();
        for (var i = 0; i < points.length; i++) {
            //debug("fit i=" + i + " point: " + points[i][0] + ", " + points[i][1]);
            var latlng = new GLatLng(points[i][0], points[i][1]);
            bounds.extend(latlng);
        }
        map.setZoom(map.getBoundsZoomLevel(bounds));
        map.setCenter(bounds.getCenter());
    };

    function debug(message) {
        if (debugEnabled) {
            $j("#debug").html(message + "<br/>" + $j("#debug").html());
        }
    };

    function loadPanoramio() {
        // TODO: check Panoramio is enabled
        // TODO: if bubble is opened, do not load Panoramio

        var serviceUrl = 'http://www.panoramio.com/map/get_panoramas.php?order=popularity&set=public&from=0&to=20';

        // pro jaky mapovy vyrez chci nahrat znacky?
        var bounds = map.getBounds();
        var north = bounds.getNorthEast().lat();
        var east = bounds.getNorthEast().lng();
        var south = bounds.getSouthWest().lat();
        var west = bounds.getSouthWest().lng();

        // prohozeni x a y je zamerne, Panoramio ma jiny souradny system (x = longtitude, y= latitude)        

        // Minimalni a maximalni povoledne hodnoty
        var latitude_min = 49.896471;
        var latitude_max = 50.220903;
        var longtitude_min = 14.153455;
        var longtitude_max = 14.667807;

        // Google mapy maji x=latitude, y=longtitude. Panoramio ma x=longtitude, y=latitude
        // longtitude = zemepisna delka, latitude = zemepisna sirka        

        // Souradnice aktualniho vyrezu mapy
        var long_min = west;
        var long_max = east;
        var lat_min = south;
        var lat_max = north;

        if (long_min < longtitude_min || long_min > longtitude_max) {
            long_min = longtitude_min;
        }
        if (long_max > longtitude_max || long_max < longtitude_min) {
            long_max = longtitude_max;
        }
        if (lat_min < latitude_min || lat_min > latitude_max) {
            lat_min = latitude_min;
        }
        if (lat_max > latitude_max || lat_max < latitude_min) {
            lat_max = latitude_max;
        }

        serviceUrl += '&miny=' + lat_min;
        serviceUrl += '&maxy=' + lat_max;
        serviceUrl += '&minx=' + long_min;
        serviceUrl += '&maxx=' + long_max;

        serviceUrl += '&size=' + panoramio_photo_size;
        serviceUrl += '&callback=?';

        //        // udelam JsonP request
        debug("loadPanoramio, serviceUrl=" + serviceUrl);
        $j.getJSON(serviceUrl, function(data, textStatus) {
            onPanoramioLoaded(data, textStatus);
        });
    };

    function onPanoramioLoaded(response, textStatus) {
        debug("onPanoramioLoaded, status=" + textStatus);
        // if response is invalid, exit
        if (!response || !response.photos || response.photos.length == 0) {
            return;
        }
        debug("loaded " + response.photos.length + " photos");
        // add panoramio icons
        for (var i = 0; i < response.photos.length; i++) {
            var photo = response.photos[i];

            var html = "<div class='panoramio-bubble'><img src='http://www.panoramio.com/img/logo-small.gif' width='119' height='25' /><br/>";
            html += "<a href='" + photo.photo_url + "'><img src='" + photo.photo_file_url + "' /></a>";
            html += "<p><strong>" + photo.photo_title + "</strong><br/>";
            html += "by <a href='" + photo.owner_url + "'>" + photo.owner_name + "</a></p>";
            html += "<p>photos provided by <a href='http://www.panoramio.com'>panoramio</a> are under the copyright of their owners.</p>";
            html += "</div>";

            var marker = getPanoramioMarker(photo.latitude, photo.longitude, photo.photo_title, photo.photo_file_url.replace(this.panoramio_photo_size, 'mini_square'), html);

            map.addOverlay(marker);
        }
    };

    function getPanoramioMarker(lat, lon, title, iconSrc, html) {
        var icon = getIcon(iconSrc, 32, 32, 16, 16);
        var title = title;
        var marker = new GMarker(new GLatLng(lat, lon), { title: title, icon: icon, draggable: false });

        GEvent.addListener(marker, 'click', function() {
            marker.openInfoWindowHtml(html);
        });

        return marker;

        //        var pos = new AGeoPoint(x, y, ACoordinateSystem.Geodetic);        

        //        var marker = new AMarker(pos, {                        
        //            'checkVisibility': false,
        //            'draggable': false,
        //            'toFrontOnHover': true,
        //            'icon' : this.getIcon(iconSrc, 32, 32, 16, 16)
        //        });         
        //        
        //        marker.addEvent('onClick', function() {
        //            marker.showBubble(html, {
        //                'width' : 290, 
        //                'maxHeight' : 500
        //            });
        //        });  

        //        marker.addEvent('onBubbleClose', function() {
        //            this.map.moveTo(
        //                marker.aGeoPoint,
        //                800,
        //                Fx.Transitions.Cubic.easeInOut
        //            );
        //        });        

        //return marker;                       
    };

    function getIcon(iconSrc, iconWidth, iconHeight, iconOffsetX, iconOffsetY) {
        // dulezite, kesujeme ikony podle jejich IconSrc
        var cachedIcon = cachedIcons[iconSrc];
        if (cachedIcon) {
            debug("cached icon src=" + iconSrc);
            return cachedIcon;
        }

        debug("new icon src=" + iconSrc);
        var icon = new GIcon();
        icon.image = iconSrc;
        icon.iconSize = new GSize(iconWidth, iconHeight);
        icon.iconAnchor = new GPoint(iconOffsetX, iconOffsetY);
        icon.infoWindowAnchor = new GPoint(iconWidth / 2, iconHeight / 2);
        cachedIcons[iconSrc] = icon;

        return icon;

        //        cachedIcon = new AIcon({
        //            'imageSize': new ASize(iconWidth, iconHeight),
        //            'iconOffset': new APoint(iconOffsetX, iconOffsetY),
        //            'fastRollover': false,                      
        //            'imageSrc': iconSrc,
        //            'shadowSrc': null
        //        });
    };

    function loadPolednicek() {
        var serviceUrl = polednicekServiceUrl; 

        // pro jaky mapovy vyrez chci nahrat znacky?
        var bounds = map.getBounds();
        var north = bounds.getNorthEast().lat();
        var east = bounds.getNorthEast().lng();
        var south = bounds.getSouthWest().lat();
        var west = bounds.getSouthWest().lng();

        serviceUrl += '?format=json';
        serviceUrl += '&north=' + north;
        serviceUrl += '&south=' + south;
        serviceUrl += '&west=' + west;
        serviceUrl += '&east=' + east;
        serviceUrl += '&callback=?';

        debug("loading Polednicek, serviceUrl=" + serviceUrl);
        $j.getJSON(serviceUrl, function(data, textStatus) {
            onPolednicekLoaded(data, textStatus);
        });

        //        GDownloadUrl(serviceUrl, function(data, responseCode) {
        //            debug("gdownload response, responseCode=" + responseCode);
        //            // To ensure against HTTP errors that result in null or bad data,
        //            // always check status code is equal to 200 before processing the data
        //            if (responseCode == 200) {
        //                polednicekParseJson(data);
        //            } else if (responseCode == -1) {
        //                //alert("Data request timed out. Please try later.");
        //            } else {
        //                //alert("Request resulted in error. Check XML file is retrievable.");
        //            }
        //        });
        //    };
    };

    function onPolednicekLoaded(response, textStatus) {
        debug("polednicek loaded");

        if (!response) {
            return;
        }
        debug("polednicek restaurants count=" + response.data.restaurants.length);
    
        var defaultIcon = polednicekCreateIcon(response.data.defaultIcon);

        for (var i = 0; i < response.data.restaurants.length; i++) {
            var bubbleContent = polednicekFormatTabOne(response.data.restaurants[i]);

            var icon = polednicekCreateIcon(response.data.restaurants[i].icon);
            if (icon == null) {
                icon = defaultIcon;
            }

            var marker = polednicekCreateMarker(response.data.restaurants[i], icon, bubbleContent);
            map.addOverlay(marker);
        }
    };

    function polednicekCreateIcon(restaurantIcon) {    
        if (restaurantIcon == null) {
            return null;
        }

        return getIcon(polednicekBaseUrl + restaurantIcon.url, restaurantIcon.width, restaurantIcon.height, restaurantIcon.anchorX, restaurantIcon.anchorY)              
    };

    function polednicekCreateMarker(restaurant, icon, bubbleContent) {

        var title = restaurant.title;
        var marker = new GMarker(new GLatLng(restaurant.point.lat, restaurant.point.lon), { title: title, icon: icon, draggable: false });

        GEvent.addListener(marker, 'click', function() {
            marker.openInfoWindowHtml(
                bubbleContent
            );
        });

        return marker;
    };

    function polednicekRenderMenu(dishes) {
        var html = "<table class=\"dishes\">";
        for (var i = 0; i < dishes.length; i++) {
            html += "<tr";
            if (i % 2 == 0) {
                html += " class=\"alternate\"";
            }
            html += ">";
            html += "<td class=\"dish-name\">" + dishes[i].name + "</td>";
            html += "<td class=\"dish-price\">";
            if (dishes[i].price > 0) {
                html += dishes[i].price + ",- Kč";
            } else {
                html += "&nbsp;"
            }
            html += "</td>";
            html += "</tr>";
        }
        if (dishes == null || dishes.length == 0) {
            html += "<tr class=\"alternate\"><td>Restaurace na dnešní den nevyplnila polední menu.</td></tr>";
        }
        html += "</table>";
        return html;
    };

    function polednicekFormatTabOne(restaurant) {
        var html = "<div class=\"bubble-polednicek\">";
        html += "<p><strong>" + restaurant.title + "</strong><br/>" + restaurant.street + "</p>";
        html += "<p class=\"bold\">Dnešní polední menu:</p>";
        html += polednicekRenderMenu(restaurant.dishes);
        html += "<p><a href=\"http://www.polednicek.cz/" + restaurant.url + "?show=thisweek\">menu na celý týden</a><span class=\"divider\">|</span>";
        html += "<a href=\"http://www.polednicek.cz/" + restaurant.url + "\">kontakt do restaurace</a></p>";
        html += "</div>";
        return html;
    };


}

