/**
 * public class ArcGIS
 *
 * base class for initialize the arcgis map. This is free javascript library 
 * with basic functionality that manages ArcGIS maps.
 */
var ArcGIS = {
	
	/**
	 * _level
	 *
	 * @access private
	 * @type {Int}
	 * @default 0
	 */
	_level : 0,
	
	/**
	 * _container
	 * 
	 * @access private
	 * @type {jQuery object}
	 * @default null
	 */
	_container : null,
	
	/**
	 * _containerWidth
	 * 
	 * @access private
	 * @type {Integer}
	 * @default 0
	 */
	_containerWidth : 0,
	
	/** 
	 * _containerHeight 
	 * 
	 * @access private
	 * @type {Integer}
	 * @default 0
	 */
	_containerHeight : 0,
	
	/**
	 * _tileSize
	 *
	 * @access private
	 * @type {Integer}
	 * @default 256
	 */
	_tileSize : 256,
	
	/**
	 * _center
	 *
	 * @access private
	 * @type {Object}
	 * @default { lat : 0, lon : 0 }
	 */
	_center : { lat : 0, lon : 0 },
	
	/**
	 * _servers
	 *
	 * @access private
	 * @type {Array}
	 * @default 
	 *
	 * 0 => "http://server.arcgisonline.com/ArcGIS/rest/services/ESRI_Imagery_World_2D/MapServer/"
	 * 1 => "http://server.arcgisonline.com/ArcGIS/rest/services/ESRI_ShadedRelief_World_2D/MapServer/"
	 * 2 => "http://server.arcgisonline.com/ArcGIS/rest/services/ESRI_StreetMap_World_2D/MapServer/"
	 */
	_servers : [],
	
	/**
	 * _currentServer
	 * 
	 * @access private
	 * @type {String}
	 * @default 'http://server.arcgisonline.com/ArcGIS/rest/services/ESRI_Imagery_World_2D/MapServer/'
	 */
	_currentServer : 'http://server.arcgisonline.com/ArcGIS/rest/services/ESRI_Imagery_World_2D/MapServer/',
	
	/**
	 * _imageType
	 * 
	 * @access private
	 * @type {String}
	 * @default png
	 * @possibile values - png, png8, png24, jpeg, gif
	 */
	_imageType : 'png',
	
	/**
	 * public function init
	 *
	 * @param container divId
	 * @param servers 
	 */
	init : function( divId, servers ) {
		
		// setup servers
		this._servers = servers;
		
		// get container
		this._container = $('#' + divId);
		
		this._containerWidth = this._container.width();
		this._containerHeight = this._container.height();
		
		// construct the grid
		this._createGrid();
		
		// add layer switcher
		this._addLayerSwitcherControl();
		
		// add zoom control
		this._addZoomControl();

		// add pan control
		this._addPanControl();
		
		// and load the tiles
		this._loadTiles();
	},
	
	/**
	 * _createGrid
	 *
	 * @access private
	 * @param {Void}
	 * @return {Void}
	 */
	_createGrid : function() {
		
		var gridCols = 4;
		var gridRows = 2;
		
		this._container.html('<div id="grid" style="width:' + (gridCols*this._tileSize) + 'px;height:' + (gridRows*this._tileSize) + 'px;"></div>');
		
		// position the grid in the center
		$('#grid').css({
			marginTop : (ArcGIS._container.height() - $('#grid').height()) / 2,
			marginLeft : (ArcGIS._container.width() - $('#grid').width()) / 2
		});
		
		// add grid divs to the grid
		for ( var i = 0; i < (gridCols*gridRows); i++) {
			$('#grid').append('<div id="gridItem-' + i + 
							'" style="width:256px;height:256px;float:left;"></div>');	
		}
		
	},
	
	/**
	 * _loadTiles
	 * 
	 * @access private
	 * @param {Void}
	 * @return {Void}
	 */
	_loadTiles : function() {
		
		var bbox = {};
		var step = {};
		switch ( this._level ) {
			case 0:
				bbox.topLon = -180;
				bbox.topLat = 90;
				bbox.bottomLon = 180;
				bbox.bottomLat = -90;
				
				step.toLeft = (bbox.bottomLon - bbox.topLon)/4;
				step.toTop = (bbox.topLat - bbox.bottomLat)/2;
				break;	
			case 1:
				bbox.topLon = -90;
				bbox.topLat = 45;
				bbox.bottomLon = 90;
				bbox.bottomLat = -45;
				
				step.toLeft = (bbox.bottomLon - bbox.topLon)/4;
				step.toTop = (bbox.topLat - bbox.bottomLat)/2;
				break;
			case 2:
				bbox.topLon = -60;
				bbox.topLat = 30;
				bbox.bottomLon = 60;
				bbox.bottomLat = -30;
				
				step.toLeft = (bbox.bottomLon - bbox.topLon)/4;
				step.toTop = (bbox.topLat - bbox.bottomLat)/2;
				break;
			case 3:
				bbox.topLon = -30;
				bbox.topLat = 15;
				bbox.bottomLon = 30;
				bbox.bottomLat = -15;
				
				step.toLeft = (bbox.bottomLon - bbox.topLon)/4;
				step.toTop = (bbox.topLat - bbox.bottomLat)/2;
				break;
			case 4:
				bbox.topLon = -20;
				bbox.topLat = 10;
				bbox.bottomLon = 20;
				bbox.bottomLat = -10;
				
				step.toLeft = (bbox.bottomLon - bbox.topLon)/4;
				step.toTop = (bbox.topLat - bbox.bottomLat)/2;
			default :
				bbox.topLon = -180;
				bbox.topLat = 90;
				bbox.bottomLon = 180;
				bbox.bottomLat = -90;
				
				step.toLeft = (bbox.bottomLon - bbox.topLon)/4;
				step.toTop = (bbox.topLat - bbox.bottomLat)/2;
				break;
		}

		var gridItemIndex = 0;
		var imageHref = '';

		for (var i = 0; i < 2; i++) {
			for (var j = 0; j < 4; j++) {
				
				imageHref = this._currentServer + 'export?bbox=' + 
					parseInt(bbox.topLon + (j*step.toLeft) + ArcGIS._center.lon) + ',' +
					parseInt(bbox.topLat - (i*step.toTop) + ArcGIS._center.lat) + ',' + 
					parseInt(bbox.topLon + (j+1)*step.toLeft + ArcGIS._center.lon) + ',' +
					parseInt(bbox.topLat - (i+1)*step.toTop + ArcGIS._center.lat)
					+'&bboxSR=&layers=&layerdefs=&size=256,256&imageSR=&format=png&transparent=false&dpi=&f=image';

				$('#gridItem-' + gridItemIndex).css({
					'background' : 'url(' + imageHref + ') 0 0 no-repeat'
				});
				gridItemIndex++;	
			}
		}
	},
	
	/**
	 * _switchLayer
	 *
	 * @access private
	 * @param {Integer} serverIndex
	 * @return {Void}
	 */
	_switchLayer : function( serverIndex ) {
		this._currentServer = this._servers[serverIndex];
	},

	/** 
	 * _addLayerSwitcherControl
	 *
	 * @access private
	 * @param {Void}
	 * @return {Void}
	 */
	_addLayerSwitcherControl : function() {
		$('#map').append('<div id="layer-switcher">' +
			'<a href="#0">ESRI Imagery World</a><br />' + 
			'<a href="#1">ESRI Shaded Relief World</a><br />' + 
			'<a href="#2">ESRI StreetMap World</a><br />' + 
			'</div>');	
			
		$('#layer-switcher').css({
			'float' : 'left',
			'position' : 'absolute'
		});
		
		// bind action
		$('#layer-switcher a').click(function() {
			
			var serverIndex = +$(this).attr('href').substr(1);
			
			ArcGIS._switchLayer( serverIndex );
			
			ArcGIS._loadTiles();
			
			return false;	
		});
	},
	
	/**
	 * _addZoomControl
	 * 
	 * @access private
	 * @param {Void}
	 * @return {Void}
	 */
	_addZoomControl : function() {
		
		// create zoom div
		$('#map').append('<div id="zoom">' +
			'<a href="#in" id="zoomin"></a>' +
			'<a href="#out" id="zoomout"></a></div>');
		
		// bind click event listener to zoomin button
		$('#zoomin').click(function() {
			
			ArcGIS._level++;
			ArcGIS._loadTiles();
			return false;	
			
		});
		
		// bind click event listener to zoomout button
		$('#zoomout').click(function() {
			
			ArcGIS._level--;
			ArcGIS._loadTiles();
			return false;
		});
	},
	
	/**
	 * _addPanControl
	 *
	 * @access private
	 * @param {Void}
	 * @return {Void}
	 */
	_addPanControl : function() {
		
		// create pan div
		$('#map').append('<div id="pan">' +
			'<a href="#up" id="up"></a>' + 
			'<a href="#left" id="left"></a>' + 
			'<a href="#center" id="center"></a>' +
			'<a href="#right" id="right"></a>' + 
			'<a href="#down" id="down"></a>' + 
			'</div>');	
		
		// move with 10 degrees to the north
		$('#up').click(function() {
			ArcGIS._center.lat += 10;
			ArcGIS._loadTiles();
			return false;	
		});
		
		// move with 10 degrees to the south
		$('#down').click(function() {
			ArcGIS._center.lat -= 10;
			ArcGIS._loadTiles();
			return false;	
		});
		
		// move with 10 degrees to the west
		$('#left').click(function() {
			ArcGIS._center.lon -= 10;
			ArcGIS._loadTiles();
			return false;
		});
		
		// move with 10 degrees to the east
		$('#right').click(function() {
			ArcGIS._center.lon += 10;
			ArcGIS._loadTiles();
			return false;	
		});
		
		// center the world map
		$('#center').click(function() {
			ArcGIS._center.lon = 0;
			ArcGIS._center.lat = 0;
			ArcGIS._loadTiles();
			return false;	
		});
	}
};
