
//= depends: zapi

/**
 * @namespace A collection of utilities for Google Maps.
 */
ZAPI.namespace('GoogleMaps').Utils = {
	/** @param {GLatLng} latLng */
	fromGLatLngToWKT: function(latLng) {
		return 'POINT(' + latLng.lng() + ' ' + latLng.lat() + ')';
	},

	/** @param {GBounds} bounds */
	fromGBoundsToBBox: function(bounds, precision) {
		precision = precision || 16;
		var sw = bounds.getSouthWest(), ne = bounds.getNorthEast();
		return sw.lng().toPrecision(precision) + ' ' + sw.lat().toPrecision(precision) + ', ' +
			ne.lng().toPrecision(precision) + ' ' + ne.lat().toPrecision(precision);
	},
	
	/** @param {Object} bbox */
	fromBBoxToGBounds: function(bbox) {
		var points = bbox.match(/([\-0-9.]+)/g);
		var glatlngbounds = new google.maps.LatLngBounds(
			new google.maps.LatLng( points[1] , points[0] ), 
			new google.maps.LatLng( points[3] , points[2] )
		);
		return glatlngbounds;
	},

	/** @param {GBounds} bounds */
	fromGBoundsToBox2d: function(bounds) {
		return 'BOX(' + this.fromGBoundsToBBox(bounds) + ')';
	},

	/**
	 * @function
	 * @param {GBounds} bounds
	 * @param {Number} zoom
	 * @param {GProjection} proj
	 */
	fromGBoundsToTiles: (function(bounds, zoom, proj) {
		var _fixTile = function(n, zoom) {
			var maxTiles = Math.pow(2, zoom);
			if (n < 0) {
				return 0;
			}
			else if (n > maxTiles) {
				return maxTiles;
			}
			else {
				return n;
			}
		};

		return function(bounds, zoom, proj) {
			var ne = proj.fromLatLngToPixel(bounds.getNorthEast(), zoom);
			var sw = proj.fromLatLngToPixel(bounds.getSouthWest(), zoom);
			var n = _fixTile(ne.y), e = _fixTile(ne.x),
				s = _fixTile(sw.y), w = _fixTile(sw.x);

			return (w / 256).floor() + ',' +
				((s / 256) + 1).floor() + ',' +
				((e / 256) + 1).floor() + ',' +
				(n / 256).floor();
		};
	}()),

	/**
	 * @function
	 * @param {GBounds} bounds
	 * @param {Number} zoom
	 * @param {GProjection} proj
	 */
	fromGBoundsToGLatLngBounds: function(bounds, zoom, proj) {
		return new google.maps.LatLngBounds(
			proj.fromPixelToLatLng(
				new google.maps.Point(bounds.minX, bounds.minY),
				zoom
			),
			proj.fromPixelToLatLng(
				new google.maps.Point(bounds.maxX, bounds.maxY),
				zoom
			)
		);
	},

	/**
	 * @function
	 * @param {GLatLngBounds} bounds
	 * @param {Number} zoom
	 * @param {GProjection} proj
	 */
	fromGLatLngBoundsToGBounds: function(bounds, zoom, proj) {
		return new google.maps.Bounds([
			proj.fromLatLngToPixel(
				bounds.getSouthWest(),
				zoom
			),
			proj.fromLatLngToPixel(
				bounds.getNorthEast(),
				zoom
			)
		]);
	},

	/**
	 * @function
	 * @param {json} polygon  // format: { 'points': [ [lng, lat], ... , [lng, lat] ] }
	 */
	fromJSONToGPolygon: function(polygon, strokeColor, strokeWeight, strokeOpacity, fillColor, fillOpacity, opts) {
		return new google.maps.Polygon(
			polygon.points.collect(function(p) {
				return new google.maps.LatLng(p[1], p[0]);
			}),
			strokeColor, strokeWeight, strokeOpacity, fillColor, fillOpacity, opts
		);
	}
};
