// http://mapki.com/mediawiki/index.php?title=Lat/Lon_To_Tile_Javascript&action=edit

Tile = function(pHash)
{
	// user set constants
	this.maxZoom = (pHash && pHash.maxzoom)?pHash.maxzoom:20;
	// ...Constants...
	this.tileSize = 256;
	this.pixelsPerLonDegree = [];
	this.pixelsPerLonRadian = [];
	this.numTiles = [];
	this.bitmapOrigo = [];
	// Note: These variable names are based on the variables names found in the
	//       Google maps.*.js code.
	this.c = 256;
	this.bc;
	this.Wa;
		
	this.fillInConstants();
}

Tile.prototype = {
	// ...Public...
	'getTileCoords': function(lat, lng, zoom) {
		return this.getTileCoordinate(lat, lng, zoom);
	},

	'getTileLatLong': function(lat, lng, zoom) {
		return this.getLatLong(lat, lng, zoom);
	},

	// ...Private...
	// Fill in the constants array
	'fillInConstants': function() {
		this.bc = 2*Math.PI;
		this.Wa = Math.PI/180;
	
		for(z = 0; z < this.maxZoom; z++) {
  			this.pixelsPerLonDegree[z] = this.c / 360;
  			this.pixelsPerLonRadian[z] = this.c / this.bc;
  			e = this.c / 2;
  			this.bitmapOrigo[z] = this.p(e,e);
  			this.numTiles[z] = this.c / 256;
  			this.c *= 2;
		}
	},

	'getBitmapCoordinate': function(a, b, c) {
  		ret = this.p(0,0);
  		ret.x = Math.floor(this.bitmapOrigo[c].x + b * this.pixelsPerLonDegree[c]);
  		e = Math.sin(a * this.Wa);
  		if(e > 0.9999) {
    		e = 0.9999;
  		}
  		if(e < -0.9999) {
    		e = -0.9999;
  		}
  		ret.y = Math.floor(this.bitmapOrigo[c].y + 0.5 * Math.log((1 + e) / (1 - e)) * -1*(this.pixelsPerLonRadian[c]));
  		return ret;
	},

	'getTileCoordinate': function(a, b, c) {
  		ret = this.getBitmapCoordinate(a, b, c);
  		ret.x = Math.floor(ret.x / this.tileSize);
  		ret.y = Math.floor(ret.y / this.tileSize);

  		return ret;
	},

	'getLatLong': function(a, b, c) {
		ret = this.p(0, 0);
		e = this.getBitmapCoordinate(a, b, c);
  		a = e.x;
		b = e.y;

		ret.x = (a - this.bitmapOrigo[c].x) / this.pixelsPerLonDegree[c];
		e = (b - this.bitmapOrigo[c].y) / (-1*this.pixelsPerLonRadian[c]);
		ret.y = (2 * Math.atan(Math.exp(e)) - Math.PI / 2) / this.Wa;
		return ret;
	},

	'p': function(x,y){
		return {x:x,y:y};
	},
	
	'getKeyholeString': function(a, b, c) {
		s = '';
		myX = a;
		myY = b;
		for(i = 17; i > c; i--) {
			rx = (fmod(myX, 2));
			myX = Math.floor(myX / 2);
			ry = (fmod(myY, 2));
			myY = Math.floor(myY / 2);
			s = this.getKeyholeDirection(rx, ry).s;
		}
		return 't'.s;
	},

	'getKeyholeDirection': function(x, y) {
		if(x == 1) {
			if(y == 1) {
				return 's';
			} else if(y == 0) {
				return 'r';
			}
		} else if(x == 0) {
			if(y == 1) {
				return 't';
			} else if(y == 0) {
				return 'q';
			}
		}
		return '';
	}
}

/*
var TileUtl = new Tile();

GEvent.addListener( map, 'click', function(overlay, point){
	var tileCoords = TileUtl.getTileCoords( point.lat(), point.lng(), map.getZoom() );
	alert( 'tile_x:' + tileCoords.x + ' tile_y:' + tileCoords.y );
*/
