
/**
 * EarthGL.Control
 * @constructor
 */

EarthGL.Control = EarthGL.Class({
	div: null,
	map: null,
	title: null,
	type: null, 
	CLASS_NAME: null,

	initialize: function() {
	},

	draw: function() {
	    this.div = document.createElement("div");
	    this.div.className = this.CLASS_NAME;
	    if (this.title) {
		this.div.title = this.title;
	    }
	    return this.div;
	}
    });

EarthGL.Control.TYPE_BUTTON = 1;

EarthGL.Control.ZoomIn = EarthGL.Class(EarthGL.Control, {	       
	type: EarthGL.Control.TYPE_BUTTON,
	title: 'zoom in',

	trigger: function() {
	    this.map.zoomIn();
	},

	CLASS_NAME: "earthgl-zoom-in"
    });

EarthGL.Control.ZoomOut = EarthGL.Class(EarthGL.Control, {
	type: EarthGL.Control.TYPE_BUTTON,
	title: 'zoom out',

	trigger: function() {
	    this.map.zoomOut();
	},

	CLASS_NAME: "earthgl-zoom-out"
    });


EarthGL.Control.Config = EarthGL.Class(EarthGL.Control, {
	type: EarthGL.Control.TYPE_BUTTON,
	title: 'Settings',

	initialize: function(baseurl) {
	    $('body').append('<div id="config_dialog" title="Settings"> \
    <label for="vscale">Vertical scaling</label> \
    <input type="text" id="vscale" value="400" /> \
    <label for="topo_res">Resolution of topography</label> \
    <select id="topo_res">\
      <option value="32x16">32x16</option>\
      <option selected="selected" value="64x32">64x32</option>\
      <option value="128x64">128x64</option>\
      <option value="256x128">256x128</option>\
      <option value="512x256">512x256</option>\
      <option value="1024x512">1024x512</option>\
    </select>\
    <button type="button" id="config_dialog_close">Close</button>\
    </div>\
');
	    this.baseurl = baseurl || "../images/";
	    $('#config_dialog').dialog({ autoOpen: false, width: 400, height: 350, zIndex: 3999 }); 

	    var that = this;
	    $('#topo_res').change(function() { that.setup_earth(); });
	    $('#vscale').change(function() { that.set_vscale(); });
	    $('#config_dialog_close').click(function() { $('#config_dialog').dialog('close'); });
	},


	trigger: function() {
	    document.getElementById('vscale').value = this.map.vscale;
	    $('#config_dialog').dialog('open');
	},


	set_vscale: function() {
	    var vscale = parseFloat(document.getElementById('vscale').value);    
	    this.map.setVScale(vscale);
	},

	setup_earth: function() {
	    var res = document.getElementById('topo_res').value;    
	    var tmp = res.split('x');
	    var topoWidth = parseInt(tmp[0],10);
	    var topoHeight = parseInt(tmp[1],10);

	    var hmin = -8043.02;
	    var hmax = 5472.27;
	    var url = this.baseurl + '/topo_' + topoWidth + 'x' + topoHeight + '.png';

	    this.map.setTopo(new EarthGL.Topo(topoWidth,topoHeight,hmin,hmax,url));
	},

	CLASS_NAME: "EarthGLControlConfig"
    });


EarthGL.Control.Rotate = EarthGL.Class(EarthGL.Control, {
	type: EarthGL.Control.TYPE_BUTTON,
	title: 'Rotate',

	trigger: function() {
	    this.map.rotate();
	},

	CLASS_NAME: "EarthGLControlRotate"
    });


EarthGL.Control.Navigation = EarthGL.Class(EarthGL.Control, {
	draw: function() {
	    //this.controller = new CameraController(this.map.canvas);
	    this.controller = {};
	    var element = this.map.canvas;

	    var controller = this;
	    var that = this;
	    var map = this.map;

	    this.onchange = null;
	    this.scaleFactor = 3.0;
	    this.dragging = false;
	    this.curX = 0;
	    this.curY = 0;
	    var opt_canvas = this.map.canvas;
	    var opt_context = null;

	    if (opt_canvas)
		this.canvas_ = opt_canvas;

	    if (opt_context)
		this.context_ = opt_context;

	    // Assign a mouse down handler to the HTML element.
	    element.addEventListener('mousedown', function(ev) { that.mousedown(ev); },false);

	    // Assign a mouse up handler to the HTML element.
	    element.addEventListener('mouseup', function(ev) { that.mouseup(ev); },false);

	    // Assign a mouse move handler to the HTML element.
	    element.addEventListener('mousemove', function(ev) { that.mousemove(ev); },false);
	    
	    // Assign a mouse scroll handler to the HTML element.
	    // better whould be to do feature detection
	    // http://perfectionkills.com/detecting-event-support-without-browser-sniffing/
	    if (jQuery.browser.mozilla) {
		// Firefox
		element.addEventListener('DOMMouseScroll', function(ev) { that.mousewheel(ev); },false);
	    }
	    else {
		// Webkit and Opera
		element.addEventListener('mousewheel', function(ev) { that.mousewheel(ev); },false);
	    }

	},


	mousedown: function (ev) {
	    this.curX = ev.clientX;
	    this.curY = ev.clientY;
	    var dragging = false;
	    if (this.canvas_ && this.context_) {
		var rect = this.canvas_.getBoundingClientRect();
		// Transform the event's x and y coordinates into the coordinate
		// space of the canvas
		var canvasRelativeX = ev.pageX - rect.left;
		var canvasRelativeY = ev.pageY - rect.top;
		var canvasWidth = this.canvas_.width;
		var canvasHeight = this.canvas_.height;
		
		// Read back a small portion of the frame buffer around this point
		if (canvasRelativeX > 0 && canvasRelativeX < canvasWidth &&
		    canvasRelativeY > 0 && canvasRelativeY < canvasHeight) {
		    var pixels = this.context_.readPixels(canvasRelativeX,
                                                            canvasHeight - canvasRelativeY,
                                                            1,
                                                            1,
                                                            this.context_.RGBA,
                                                            this.context_.UNSIGNED_BYTE);
		    if (pixels) {
			// See whether this pixel has an alpha value of >= about 10%
			if (pixels[3] > (255.0 / 10.0)) {
			    dragging = true;
			}
		    }
		}
	    } else {
		dragging = true;
	    }

	    this.dragging = dragging;
	},

	mouseup: function (ev) {
	    if (this.dragging) {
		this.map.events.triggerEvent('moveend');	    
	    }

	    this.dragging = false;
	},

	mousemove: function (ev) {
	    if (this.dragging) {
		// Determine how far we have moved since the last mouse move
		// event.
		var curX = ev.clientX;
		var curY = ev.clientY;
		var deltaX = (this.curX - curX) / this.scaleFactor;
		var deltaY = (this.curY - curY) / this.scaleFactor;
		this.curX = curX;
		this.curY = curY;
		// Update the X and Y rotation angles based on the mouse motion.
		this.map.lonC = (this.map.lonC + deltaX) % 360;
		this.map.latC = (this.map.latC - deltaY);
		// Clamp the X rotation to prevent the camera from going upside
		// down.
		if (this.map.latC < -90) {
		    this.map.latC = -90;
		} else if (this.map.latC > 90) {
		    this.map.latC = 90;
		}
	    
		this.map.draw();

		this.map.events.triggerEvent('move');
	    }
	},

	mousewheel: function (ev) {
	    // http://www.switchonthecode.com/tutorials/javascript-tutorial-the-scroll-wheel
	    var wheelData = ev.detail ? ev.detail * -1 : ev.wheelDelta / 40;
	    
	    if (wheelData > 0) {
		this.map.zoomIn();
	    }
	    else {
		this.map.zoomOut();
	    }

	    //ev.stopPropagation();
	    ev.preventDefault();
	}


    });


EarthGL.Control.CameraPosition = EarthGL.Class(EarthGL.Control, {
	
	title: 'Camera position (longitude, latitude and distance)',

    initialize: function(options) {
        EarthGL.Control.prototype.initialize.apply(this, arguments);
    },
    
    draw: function() {
	    // called super-class draw method to create a div
	    EarthGL.Control.prototype.draw.apply(this, arguments);
	    //EarthGL.Control.draw.apply(this, arguments);
	    this.map.events.register('zoomend',this,this.redraw);
	    this.map.events.register('moveend',this,this.redraw);
	    this.map.events.register('move',this,this.redraw);
	    this.redraw();
	    return this.div;
	},
    
    redraw: function() {
	    this.div.innerHTML = " " + (this.map.lonC.toFixed(2))
	      + ", " + (this.map.latC.toFixed(2)) 
              + ", " + (this.map.EarthRadius*this.map.getDistance()) + ' m'; 
	    ;
	},

	CLASS_NAME: "EarthGLControlCameraPosition"
    });

