﻿function DoGoogle(cx, ie) {
    var q = document.forms[0]["q"].value;

    window.open("http://www.google.com.mx/cse?cx=" + cx + "&ie=" + ie + "&q=" + q);

    return false;
}


function JpsGoogleMaps() {

    function Event() {

        var _subscribers = [];

        this.AddHandler = function (func) {
            if (!_subscribers[func])
                _subscribers[_subscribers.length] = func;
        }

        this.RemoveHandler = function (func) {
            for (i = 0; i < _subscribers.length; i++) {
                if (_subscribers[i] == func)
                    _subscribers.splice(i);
            }
        }

        this.Fire = function (args) {
            for (var i in _subscribers) {
                _subscribers[i](args);
            }
        }

    }

    this.ShowRouteCallBack = new Event();
    this.ShowRouteErrorCallBack = new Event();
    this.MarkerHoverCallBack = new Event();
    this.MarkerOutCallBack = new Event();
    this.MarkerClickCallBack = new Event();

    var _maps = new Array();

    var _geocodeService = null;
    var _directionsService = null;
    var _directionsDisplay = null;

    this.AddMap = function (div, zoomLevel) {

        var divElement = div;

        if (typeof div == "string") {
            divElement = document.getElementById(div);
        }

        if (_maps[divElement] != null)
            throw "A map with this id already exists";

        _maps[div] = new JpsMap(div, this, zoomLevel);
    }

    this.GetMap = function (div) {
        var divElement = div;

        if (typeof div == "string") {
            divElement = document.getElementById(div);
        }


        return _maps[divElement];
    }

    this.GetMapByIndex = function (idx) {
        var i = 0;

        for (key in _maps) {
            if (i == idx)
                return _maps[key];

            i++;
        }
    }

    function GeocodeServiceInternal() {
        if (_geocodeService == null)
            _geocodeService = new google.maps.Geocoder();

        return _geocodeService;
    }

    this.GeocodeService = function () {
        return GeocodeServiceInternal();
    }

    this.DirectionsService = function () {
        if (_directionsService == null)
            _directionsService = new google.maps.DirectionsService();

        return _directionsService;
    }

    this.DirectionsDisplay = function () {
        if (_directionsDisplay == null) {
            var rendererOptions = {

            }
            _directionsDisplay = new google.maps.DirectionsRenderer(rendererOptions);
        }

        return _directionsDisplay;
    }

    this.Geocode = function (address, successFunc, errorFunc) {

        GeocodeServiceInternal().geocode({ 'address': address }, function (results, status) {
            if (status == google.maps.GeocoderStatus.OK) {
                successFunc(results[0].geometry.location);
            } else {
                errorFunc();
            }
        });

    }

    function JpsMap(div, parent, zoomLevel) {

        var _div = div;
        var _map = null;
        var _parent = parent;


        var _zoomLevel = 7;

        if (zoomLevel != undefined)
            _zoomlevel = zoomLevel;

        var _markerArray = [];
        var _infoWindow = null;

        var myOptions = {
            language: "nl",
            mapTypeId: google.maps.MapTypeId.ROADMAP,
            zoom: _zoomLevel
        }

        _map = new google.maps.Map(div, myOptions);
        _infoWindow = new google.maps.InfoWindow();

        var _address = "";
        var _place = "";
        var _postalcode = "";

        var _markers = [];
        var _bounds = new google.maps.LatLngBounds();

        this.getZoom = function () {
            return _map.getZoom();
        }

        this.setZoom = function (lvl) {
            _map.setZoom(lvl);
        }

        // Expose
        this.Markers = _markers;       

        function JpsMarker(id, marker) {
            this.Id = id;
            this.Marker = marker;

            var me = this;

            google.maps.event.addListener(marker, "click", function () {
                _parent.MarkerClickCallBack.Fire(args = { "map": _map, "marker": me });
            });
            google.maps.event.addListener(marker, "mouseover", function () {
                _parent.MarkerHoverCallBack.Fire(args = { "map": _map, "marker": me });
            });
            google.maps.event.addListener(marker, "mouseout", function () {
                _parent.MarkerOutCallBack.Fire(args = { "map": _map, "marker": me });
            });
        }

        this.AddMarkerWithCustomIcon = function(icon, location, isDraggable, infoWindowText)
        {
            if (typeof location == "string") {
                _parent.Geocode(location, function (latLng) {
                    DoIt(id, latLng, isDraggable, infoWindowText);
                });
            }
            else {
                DoIt(icon, location, isDraggable, infoWindowText);
            }

            function DoIt(icon, latLng, isDraggable, infoText) {                

                var marker = new google.maps.Marker({
                    map: _map,
                    icon: icon,
                    draggable: isDraggable,
                    animation: google.maps.Animation.DROP,
                    position: latLng
                });

                if (infoWindowText != null) {
                    var infowindow = new google.maps.InfoWindow({
                        content: infoWindowText
                    });
                    google.maps.event.addListener(marker, 'click', function (infoWindowText) {
                        infowindow.open(_map, marker);
                    });
                }

                jm = new JpsMarker(null, marker);
                _markers.push(jm);
                _bounds.extend(latLng);
            }
        }

        this.AddMarker = function (id, location, isDraggable, infoWindowText, markerImageUrl) {

            if (typeof location == "string") {
                _parent.Geocode(location, function (latLng) {
                    DoIt(id, latLng, isDraggable, infoWindowText, markerImageUrl);
                });
            }
            else {
                DoIt(id, location, isDraggable, infoWindowText, markerImageUrl);
            }

            function DoIt(id, latLng, isDraggable, infoText, imageUrl) {

                var icon;

                if (imageUrl != null) {
                    icon = new google.maps.MarkerImage(imageUrl);
                    // icon = new google.maps.MarkerImage(imageUrl, new google.maps.Size(32, 37),
                    // new google.maps.Point(0, 0),
                    // new google.maps.Point(12, 27),
                    //  new google.maps.Size(24, 27));

                    //                var markerShape = { coord: [0, 32, 37, 0], type: "poly" };
                }
                else {

                }

                var marker = new google.maps.Marker({
                    map: _map,
                    icon: icon,
                    draggable: isDraggable,
                    animation: google.maps.Animation.DROP,
                    position: latLng
                });
                
                if (infoWindowText != null) {
                    var infowindow = new google.maps.InfoWindow({
                        content: infoWindowText
                    });
                    google.maps.event.addListener(marker, 'click', function (infoWindowText) {
                        infowindow.open(_map, marker);
                    });
                }                

                jm = new JpsMarker(id, marker);
                _markers.push(jm);
                _bounds.extend(latLng);               
            }

        }

        this.CenterAndZoom = function (latLng, zoom) {
            _map.setCenter(latLng);
            _map.setZoom(zoom);
        }

        this.FitBounds = function (minZoomLevel) {
            _map.fitBounds(_bounds);
            if (minZoomLevel != undefined) {
                var listener = google.maps.event.addListener(_map, "idle", function () {
                    if (_map.getZoom() > minZoomLevel) _map.setZoom(minZoomLevel);
                    google.maps.event.removeListener(listener);
                });
            }
        }

        this.ShowRoute = function (origin, destination, waypoints) {

            var request = {
                region: "mx",
                language: "es",
                origin: origin,
                destination: destination,
                travelMode: google.maps.DirectionsTravelMode.DRIVING
            };

            if (waypoints != null) {
                var wpts = [];

                for (var i = 0; i < waypoints.length; i++) {
                    wpts.push({
                        location: waypoints[i],
                        stopover: true
                    });
                }

                request.waypoints = wpts;
                request.optimizeWaypoints = true;
            }

            var x = new google.maps.DirectionsService();

            _parent.DirectionsService().route(request, function (response, status) {
                if (status == google.maps.DirectionsStatus.OK) {

                    _parent.ShowRouteCallBack.Fire(args = { "map": _map, "origin": origin, "destination": destination, "route": response });

                    _parent.DirectionsDisplay().setMap(_map);
                    _parent.DirectionsDisplay().setDirections(response);
                    // GShowSteps(response);
                }
                else {
                    _parent.ShowRouteErrorCallBack.Fire(args = { "status": status });
                }

            });
        }

        this.ClearRoute = function () {
            _parent.DirectionsDisplay().setMap(null);
        }

        function GShowSteps(directionResult) {
            // For each step, place a marker, and add the text to the marker's
            // info window. Also attach the marker to an array so we
            // can keep track of it and remove it when calculating new
            // routes.
            var myRoute = directionResult.routes[0].legs[0];

            for (var i = 0; i < myRoute.steps.length; i++) {
                var marker = new google.maps.Marker({
                    position: myRoute.steps[i].start_point,
                    map: _map
                });

                GAttachInstructionText(marker, myRoute.steps[i].instructions);
                _markerArray[i] = marker;
            }
        }

        function GAttachInstructionText(marker, text) {
            google.maps.event.addListener(marker, 'click', function () {
                stepDisplay.setContent(text);
                stepDisplay.open(_map, marker);
            });
        }

        function GoogleMapShowAddress(latLng, zoomLevel) {
            _map.setCenter(latLng);

            var marker = new google.maps.Marker({
                map: map,
                position: latLng
            });
        }

    }


}

var googleMaps = new JpsGoogleMaps();


function GoogleMapAddEvent(o, e, f) {
    if (o) {
        if (o.addEventListener) {
            o.addEventListener(e, f, true);
            return true;
        }
        else if (o.attachEvent) {
            return o.attachEvent("on" + e, f);
        } else {
            return false;
        }
    }
}

