/*
 * Copyright (c) 2009. Sproozi.com - All rights reserved
 */

Sproozi.namespace("sproozi.map");

sproozi.map.Point = function (latitude, longitude) {
    this.latitude = latitude;
    this.longitude = longitude;
};
sproozi.map.Point.prototype = {
    name : null,
    marker : null,
    toString : function () {
        return this.name + " [" + this.latitude + ", " + this.longitude + "]";
    },
    distance : function (point) {

        var lat1 = this.latitude.toRadians();
        var lat2 = point.latitude.toRadians();
        var R = 6378100; // m
        return d = Math.acos(Math.sin(lat1) * Math.sin(lat2) +
                             Math.cos(lat1) * Math.cos(lat2) *
                             Math.cos((point.longitude - this.longitude).toRadians())) * R;
    },
    bearing : function(point) {
        var lat1 = this.latitude.toRadians();
        var lat2 = point.latitude.toRadians();

        var dLon = (point.longitude - this.longitude).toRadians();
        var y = Math.sin(dLon) * Math.cos(lat2);
        var x = Math.cos(lat1) * Math.sin(lat2) -
                Math.sin(lat1) * Math.cos(lat2) * Math.cos(dLon);
        return ( Math.atan2(y, x).toDegrees() + 360 ) % 360;
    }
};

sproozi.map.Location = function (latitude, longitude) {
    sproozi.map.Location.baseConstructor.call(this, latitude, longitude);
};
Sproozi.extend(sproozi.map.Location, sproozi.map.Point);
Sproozi.populate(sproozi.map.Location.prototype, {
    links : null,
    title : null,
    relevance : -1,
    toString : function () {
        var str = "";
        for (prop in this) {
            str += prop + " : " + this[prop] + "\n";
        }
        return str;
    }
});

sproozi.map.Location.Link = function () {
};
sproozi.map.Location.Link.prototype = {
    title : null,
    url : null,
    summary : null,
    size : -1,
    toString : function () {
        var str = "";
        for (prop in this) {
            str += prop + " : " + this[prop] + "\n";
        }
        return str;
    }
};

sproozi.map.Map = function (element) {
    this.element = element;
};
sproozi.map.Map.prototype = {
    element: null,
    center : null,
    createMarker : function(point, infoWindowFunction, image) {
        alert("createMarker: has not been implemented for this provider.");
    },
    clearMarkers : function () {
        alert("clearMarkers: has not been implemented for this provider.");
    },
    setCenter : function (point) {
        this.center = point;
        this.centerMap();
    },
    getCenter : function () {
        return this.center;
    },
    centerMap : function () {
        alert("centerMap: has not been implemented for this provider.");
    },
    zoom : function (level) {
        alert("zoom: has not been implemented for this provider.");
    },
    onReady : function () {
    },
    createContent : function (className, content) {
        alert("createContent: has not been implemented for this provider.");
    }
};

sproozi.map.GeoCoder = function () {

};
sproozi.map.GeoCoder.prototype = {
    getPoint : function(location, point, callback) {
        alert("createPoint not implemented!");
    },
    getAddress : function (point, callbacl) {
        alert("getAddress not implemented!");
    },
    getLocalityName : function(point, callback) {
        alert("getLocalityName not implemented!");
    }
};


google.load("maps", "2", {"other_params":"sensor=false"});

sproozi.map.Map.GoogleMapsImplementation = function(element) {
    sproozi.map.Map.GoogleMapsImplementation.baseConstructor.call(this, element);

    var self = this;
    google.setOnLoadCallback(function () {
        self.map = new google.maps.Map2(document.getElementById("map"));
        //self.map.addControl(new GMapTypeControl());
        self.map.addControl(new GSmallZoomControl3D());
        self.onReady();
    });

    // Alter the objects so they work correctly with our now loaded mapping implementation.
    sproozi.map.Point.prototype.getLatLng = function() {
        return new google.maps.LatLng(this.latitude, this.longitude);
    };

};
Sproozi.extend(sproozi.map.Map.GoogleMapsImplementation, sproozi.map.Map);
Sproozi.populate(sproozi.map.Map.GoogleMapsImplementation.prototype, {
    map : null,
    centerMap : function () {
        this.map.setCenter(this.center.getLatLng());
    },
    setZoom : function (level) {
        this.map.setZoom(level);
    },
    createMarker : function (point, infoWindowFunction, image, onDragFunction) {

        var marker;
        var options = {};
        if (image != undefined && image != null) {
            var icon = new GIcon(G_DEFAULT_ICON);
            icon.image = image;
            var imageObj = new Image();
            imageObj.src = image;
            icon.iconSize = new GSize(imageObj.width, imageObj.height);
            options.icon = icon;
        }

        if (onDragFunction != undefined || onDragFunction != null) {
            options.draggable = true;
        }

        marker = new GMarker(point.getLatLng(), options);

        if (infoWindowFunction != undefined || infoWindowFunction != null) {
            marker.show = function() {
                marker.openInfoWindowHtml(infoWindowFunction.call(point));
            };
            GEvent.addListener(marker, "click", marker.show);
        }

        if (onDragFunction != undefined || onDragFunction != null) {
            marker.drag = function () {
                onDragFunction.call(point);
            }
            GEvent.addListener(marker, "dragend", marker.drag);
        }
        point.marker = marker;
        this.map.addOverlay(marker);
    },
    clearMarkers : function () {
        this.map.clearOverlays();
    },
    createContent : function (className, content) {
        var divTag = document.createElement("div");
        divTag.className = className;
        divTag.innerHTML = content;
        var container = this.map.getContainer();
        container.appendChild(divTag);
    }

});

sproozi.map.GeoCoder.GoogleImplementation = function() {
    sproozi.map.GeoCoder.GoogleImplementation.baseConstructor.call(this);
    this.geocoder = new GClientGeocoder();

};
Sproozi.extend(sproozi.map.GeoCoder.GoogleImplementation, sproozi.map.GeoCoder);
Sproozi.populate(sproozi.map.GeoCoder.GoogleImplementation.prototype, {
    geocoder : null,
    getAddress : function (point, callback) {
        this.geocoder.getLocations(point.getLatLng(), function (response) {
            if (!response || response.Status.code != 200) {

            } else {
                callback.call(point, response.Placemark[0].address);
            }
        });
    },
    getLocalityName : function (point, callback) {
        this.geocoder.getLocations(point.getLatLng(), function (response) {
            if (!response || response.Status.code != 200) {

            } else {
                callback.call(point, response.Placemark[0].AddressDetails.Country.AdministrativeArea.SubAdministrativeArea.Locality.LocalityName);
            }
        });
    },
    getPoint : function (location, point, callback) {

        this.geocoder.getLatLng(location, function(latlng) {
                    if (!latlng) {
                        alert("Could not find place.");
                    } else {
                        point.latitude = latlng.lat();
                        point.longitude = latlng.lng();
                        callback.call(point);
                    }
                });
    }


});


