//"gExplorer to explore "Places"
//written by: Paul van Dinther
//            Dinther Product Design
//            Software development and specialists in simulation
//            email: vandinther@gmail.com

    //multiply a meter with this to get a delta latitude (1/60 of a degree is 1852 meters)
    var metersToLocalLat = 0.0000089992800575953923686105111591073; 
    var halfmetersToLocalLat = metersToLocalLat/2; 

    //multiply a delta latitude with this to get meters (1/60 of a degree is 1852 meters)
    var deltaLatitudeToMeters = 111120;
    
    //multiply with this to get angle in radians
    var degreesToRad = 0.017453292519943;

    //this is a full circle equivalent of 360 degrees expressed in radians
    var radianCircle = 57.295779513082320876798154814105;

    var ge = null;
    var map = null;
    var myExplorer = null;
    var oneOnly = true;
    var lastMill;
    
    var leftKey = false;
    var rightKey = false;
    var upKey = false;
    var downKey = false;
    var shiftKey = false;
    var ctrlKey = false;
    var altKey = false;
    var zKey = false;
    var sideLeftKey = false;
    var sideRightKey = false;
    var spaceKey = false;
    var capsKey = false;

    var mouseIsDown=false;
    var spin = 0;
    var currentCam = null;
    var distanceCutOff = 4000;
    var now = 0;
    var playBtn = null;
    
    var cardTextCount = 15;
    var collection = '';
    var toNormalTextTimeout = 0;
    var toggleBuildingsState = true;
    var toggleGrayBuildingsState = false;
    var toggleBordersState = false;
    var camBearingDistanceTilt = null;
    var camBearingDistanceTiltToHitTest = null;
    var lowUpdate = 0;
    var frameCount = 0;
    var frames = new Array();
    var frameSampleTime = 0;
    var bannerTimeOut = 0;
    var showBanner = true;
    var viewTarget = null;
    var viewTargetDistance = 0;

    var fullScreenState = false;
    var placesStart = null;
    
    var normalLeft = 0;
    var normalTop = 0;
    var normalWidth = 0;
    var normalHeight = 0;
    var mapVisible = false;
    var qsParm = new Array();
    
    var applicationTitle = ''
    var mouseMoveAge = 100000;
    var mouseClickAge = 100000;
    var mousePauseDuration = 3;
    var mouseIndexLast = 0;
    var mouseY = 0;
    var mouseX = 0;
    var qs = new Querystring();
    var showOverlays = true;
    var groundsign = null;
    var textInputFocus = false;
    var placeMaking = false;
    var exploring = false;
    var tourPlaying = false;
    var showHelp = 0;
    var helpSwivel = new smooth(90,90,500,0.0,100,10);  //svalue, starget, smaxrate, srate, sgain, sloose
    var recorder = new tourRecorder(5100); //allow max of 720 points (3 minutes)
    var doFreeze = false;
    var windowFocusDone = false;
    
    
    //Attach event handlers to recorder events
    recorder.onStopRecording = function (){ handleStopRecording(); }
    recorder.onStartRecording = function (){ handleStartRecording(); }
    recorder.onStopPlayback = function (){ handleStopPlayback(); }
    recorder.onStartPlayback = function (){ handleStartPlayback(); }
    recorder.onInitFrame = function(){ handleInitFrame(); }
    recorder.onPlayback = function(){ handlePlayback(); }
    recorder.onGetCamera = function(){ return handleGetCamera(); }
    
    var recordCountDown = -1;
    var myCard = new card();
    var earthCard = null;
    var noMoveTimeOut = 10;

    function card(){
        this.latitude = 0;
        this.longitude = 0;
        this.altitude = 0;
        this.heading = 0;
        this.pitch = 0;
        this.speedFactor = 0;
        this.imageId = 0;
        this.name = '';
        this.description = '';
        this.duration = 0;
        this.kmzUrl = undefined;
    }

    
    function init(){
    Querystring();
    if (qs.get("cd") == null){alert('Card ID is missing in URL parameters.'); window.location="../places.htm";}
    

    //masterHost = 'http://dinther.dnsalias.com/planetinaction/places/';
    masterHost = 'http://' + document.domain + '/places/';
   	applicationTitle = 'Places v1.0 by PlanetInAction.com';    
         
    //google.load("earth", "1", {'other_params': 'sensor=false' });
    lastMill = (new Date()).getTime();

    document.getElementById('friend_nam').onblur = function () {textInputFocus = false;}
	document.getElementById('friend_nam').onfocus = function () {textInputFocus = true;}
    document.getElementById('kmldescription').onblur = function () {textInputFocus = false;}
	document.getElementById('kmldescription').onfocus = function () {textInputFocus = true;}	

    google.earth.createInstance("map3d", initCB, failureCB);
    if (GBrowserIsCompatible()) {
        map = new GMap2(document.getElementById("map"));
        map.setCenter(new GLatLng(51.893606, 4.308849), 12);
        var customUI = map.getDefaultUI();
        customUI.controls.menumaptypecontrol = false;
        map.setUI(customUI);        
    }
}

function updateMousePause(deltaTime){
    if (mouseClickAge < mousePauseDuration){
        var pauseDuration = (mousePauseDuration - mouseClickAge)/ mousePauseDuration;
        mousePauseAmountIcon.getSize().setX(35 * pauseDuration);
        mousePauseIcon.setVisibility(!clickToExplore.getVisibility());
        mousePauseAmountIcon.setVisibility(!clickToExplore.getVisibility());
    } else if (mousePauseAmountIcon.getVisibility()){
        mousePauseAmountIcon.setVisibility(false);
        mousePauseIcon.setVisibility(false);
        handleEndMousePause();
    }
}

function handleEndMousePause(){
    if (placeMaking && !recorder.recording && !recorder.playing){
        overlaysState(true);
    }
}

function initCB(object) {
    ge = object;
    ge.getWindow().setVisibility(true);
    ge.getOptions().setStatusBarVisibility(false);
    ge.getNavigationControl().setVisibility(ge.VISIBILITY_HIDE);
    ge.getOptions().setFlyToSpeed(ge.SPEED_TELEPORT);
    ge.getLayerRoot().enableLayerById(ge.LAYER_BUILDINGS, 1);
    createCompassGauge(30,50);
    createFullScreenIcon();
    createNormalScreenIcon();
    createRecordingIcon(16,16);
    createToNormalText();
    createKeys(-1,0);
    createOneIcon();
    createTwoIcon();
    createThreeIcon();
    createFourIcon();
    createMousePauseIcon(180,1);
    createClickToExplore();
    createLogo();

    leftKey = false;
    rightKey = false;
    upKey = false;
    downKey = false;
    initExplorer();
    collection = qs.get("col");
    if (collection == undefined){alert('URL is incomplete. The collection name is missing from URL parameters.'); window.location="index.htm";}
    var kmlurl = location.href.substring(0,location.href.lastIndexOf("/")+1) + 'cards/' + collection + '/' + qs.get("cd") + '.kml';
    document.getElementById("gelink").href = kmlurl;
    if (qs.get("cd") != null){ google.earth.fetchKml(ge, kmlurl, initKML);}
    else {initPlace();} 
    google.earth.addEventListener(ge, "frameend", moveexplorer);
    google.earth.addEventListener(ge.getWindow(), 'mouseup', setMouseUp);
    google.earth.addEventListener(ge.getWindow(), 'mousedown', setMouseDown);
    google.earth.addEventListener(ge.getWindow(), 'mousemove', setMouseMove);
    google.earth.addEventListener(ge.getView(), 'viewchange', setViewChange);
    google.earth.addEventListener(ge.getView(), 'viewchangeend', setViewChange); 
}


function initMOD(object){  
    if (!object) {
        // wrap alerts in API callbacks and event handlers
        // in a setTimeout to prevent deadlock in some browsers
        setTimeout(function() { alert('Card ' + qs.get("cd") + ' could not be found.'); }, 0);
    return;
    }
    
    ge.getFeatures().appendChild(object);
}

function initKML(object){  
    if (!object) {
        // wrap alerts in API callbacks and event handlers
        // in a setTimeout to prevent deadlock in some browsers
        setTimeout(function() { alert('Bad or null KML.'); }, 0);
    return;
    }
    
    ge.getFeatures().appendChild(object);
    
    walkKmlDom(object, function() {
        if (this.getType() == 'KmlTour') {
            earthCard = this;
            return false; // stop the DOM walk here.
        }
    });
    if (earthCard == null){
        alert('Invalid Place Card.');
        //window.location="../places.htm";
    }   
    initEmbeddedKml();
    //load additional kml/kmz file if defined
    if (myCard.kmzUrl != undefined){
        google.earth.fetchKml(ge, myCard.kmzUrl, initFreeKML);        
    }
    initPlace();
}

function initFreeKML(object){  
    if (!object) {
        // wrap alerts in API callbacks and event handlers
        // in a setTimeout to prevent deadlock in some browsers
        setTimeout(function() { alert('Bad or null KML.'); }, 0);
    return;
    }  
    ge.getFeatures().appendChild(object);
}

function initEmbeddedKml(){
    myCard.name = earthCard.getName();
    myCard.description = earthCard.getDescription();      
    var paramdata = earthCard.getAddress();
    var params = paramdata.split(",");
    myCard.latitude = parseFloat(params[0]);
    myCard.longitude = parseFloat(params[1]);
    myCard.altitude = parseFloat(params[2]);
    myCard.heading = parseFloat(params[3]);
    myCard.pitch = parseFloat(params[4]);
    myCard.speedFactor = parseFloat(params[5]);
    myCard.imageId = parseInt(params[6]);
    myCard.duration = parseInt(params[7]);
    //this param may not be present as it is manually added for demo purposes
    if (params[8] != undefined) {
        myCard.kmzUrl = params[8];
    }
}

function resetPlace(){
    if (placeMaking) { togglePlaceMaker(); }
    recorder.clear();
    shareBtnDisabled(true);
    playBtnDisabled(true);
    recordBtnDisabled(false);
    previousTextBtnDisabled(false);
    nextTextBtnDisabled(false);    
    initEmbeddedKml();
    initPlace();
}

function initPlace(){
    recorder.stopPlayback();
    recorder.stopRecording();
    myExplorer.latitude = myCard.latitude;
    myExplorer.longitude = myCard.longitude;
    myExplorer.height.set(myCard.altitude);
    myExplorer.heading.set(myCard.heading);
    myExplorer.targetHeadTilt.set(myCard.pitch);
    myExplorer.defaultSpeedFactor = myCard.speedFactor;
    setCardImage(myCard.imageId);
    document.getElementById("friend_nam").value = myCard.name;
    if (myCard.name != ''){
        document.getElementById("placetitle").innerHTML = '&nbsp;' + myCard.name;
    }
    if (myCard.description != ''){
        document.getElementById("message").innerHTML = myCard.description;
    }
    document.getElementById("your_link").value = getPlaceURL();
    setSpeed(myExplorer.defaultSpeedFactor);
    freeze();
    overlaysState(true);
    lowUpdate = 0;
    exploring = false;
    updateView();
}

function setSpeed(value){
  myExplorer.defaultSpeedFactor = value;
  document.getElementById("speed1").checked = false;
  document.getElementById("speed2").checked = false;
  document.getElementById("speed3").checked = false;
  if (myExplorer.defaultSpeedFactor > 0.7){ document.getElementById("speed3").checked = true;}
  else if (myExplorer.defaultSpeedFactor > 0.4){ document.getElementById("speed2").checked = true;}
  else { document.getElementById("speed1").checked = true;}  
  linkChanged();
}

function setExplorer(){
    recorder.stopPlayback();
    if (!placeMaking && !recorder.recording && !recorder.playing){
        playPlace(); 
        if (tourPlaying){
            setExplorerToCam();
        }
        exploring = true;
        ge.getTourPlayer().setTour(null);
        tourPlaying = false;
    }
}

function overlaysState(startup){
    if (startup){
        cardText.setVisibility(true);
        clickToExplore.setVisibility(!placeMaking);
        compassGauge.setVisibility(false);
        compassIndicator.setVisibility(false);
        fullScreenIcon.setVisibility(false);
        keys.setVisibility(false);
        ge.getOptions().setStatusBarVisibility(false);
        ge.getNavigationControl().setVisibility(ge.VISIBILITY_HIDE);
    }
    else{
        cardText.setVisibility(false);
        clickToExplore.setVisibility(false);
        compassGauge.setVisibility(true);
        compassIndicator.setVisibility(true);
        fullScreenIcon.setVisibility(!placeMaking);
        keys.setVisibility(true);
        ge.getOptions().setStatusBarVisibility(true);
        ge.getNavigationControl().setVisibility(ge.VISIBILITY_HIDE);
    }
}

function initExplorer() {
    myExplorer = new PIA_gexplorer(0, 0, 0, 0, 0, 0);
} 

function setCardImage(imageId){
    myCard.imageId = imageId;
    if (cardText !=null){ ge.getFeatures().removeChild(cardText);}
    var cardURL = '';
    if (myCard.imageId > 4999) { cardURL = masterHost + 'cardtext/'+ 'cardtext' + imageId + '.jpg'; }
    else if (imageId > -1){ cardURL = masterHost + 'cardtext/' + 'cardtext' + imageId + '.png'; }
    createCardText(cardURL);

}

function incCardText(){
    if (myCard.imageId > 999){myCard.imageId = -1;}
    if (myCard.imageId == cardTextCount){myCard.imageId = -1;}
    setCardImage(myCard.imageId+1);
    linkChanged();
}

function decCardText(){
    if (myCard.imageId > 999){myCard.imageId = 0;}
    if (myCard.imageId == 0){myCard.imageId = cardTextCount+1;}
    setCardImage(myCard.imageId-1);
    linkChanged();
}

function linkChanged(){
    if (placeMaking){
        document.getElementById("your_link").value = 'Click "Share this place" in Place Maker for a new link';
        shareBtnDisabled(false);
    }    
}

function freeze(){
    myExplorer.freeze();
    mouseMoveAge = 10000;
    //mouseClickAge = 0;
    spin = 0;
    doFreeze = false;
}

function failureCB(object) {
    window.location="../installgoogleearth.htm"
}

function Querystring(qs) { // optionally pass a querystring to parse
	this.params = {};
	
	if (qs == null) qs = location.search.substring(1, location.search.length);
	if (qs.length == 0) return;

// Turn <plus> back to <space>
// See: http://www.w3.org/TR/REC-html40/interact/forms.html#h-17.13.4.1
	qs = qs.replace(/\+/g, ' ');
	var args = qs.split('&'); // parse out name/value pairs separated via &
	

// split out each name=value pair
	for (var i = 0; i < args.length; i++) {
		var pair = args[i].split('=');
		var name = decodeURIComponent(pair[0]);
		
		var value = (pair.length==2)
			? decodeURIComponent(pair[1])
			: name;
		
		this.params[name] = value;
	}
}

Querystring.prototype.get = function(key, default_) {
	var value = this.params[key];
	return (value != null) ? value : default_;
}

Querystring.prototype.contains = function(key) {
	var value = this.params[key];
	return (value != null);
}

function playPlace(){
    if (!placeMaking){
        overlaysState(false);
        //playback the kml tour data if there is any.
        if (myCard.duration > 1){
    	   exploring = false;
           ge.getTourPlayer().setTour(earthCard);
           ge.getTourPlayer().play();
           tourPlaying = true;
        }
        else{
	       exploring = true;
        }	    
	}
}

function handleStopRecording(){
    document.getElementById('recordbtn').src = 'recordtour.png';
    recordingIcon.setVisibility(false);
    overlaysState(true);
    playBtnDisabled(!recorder.recordingIndex>0);
    previousTextBtnDisabled(false);
    nextTextBtnDisabled(false);
    doFreeze = true;
    recorder.initFrame(0);
    document.getElementById('kmldata').value = recorder.asCsv();
}

function handleStartRecording(){
    document.getElementById('recordbtn').src = 'finishtour.png';
    recordingIcon.setVisibility(true);
    overlaysState(false);
    playBtnDisabled(true);
    previousTextBtnDisabled(true);
    nextTextBtnDisabled(true);
    linkChanged();
}

function handleStopPlayback(){
    document.getElementById('playbtn').src = 'play.png';
    recordBtnDisabled(false);
    overlaysState(true);
    previousTextBtnDisabled(false);
    nextTextBtnDisabled(false);
    doFreeze = true;  
    setExplorerToCam();        
}

function handleStartPlayback(){
    document.getElementById('playbtn').src = 'stop.png';
    overlaysState(false);
    recordBtnDisabled(true);
    previousTextBtnDisabled(true);
    nextTextBtnDisabled(true);
}

function handleInitFrame(){
    handlePlayback();
    setExplorerToCam();
    
    //setExplorerToRecorder();
}

function handlePlayback(){
    var myCam = ge.getView().copyAsCamera(ge.ALTITUDE_ABSOLUTE);
    myCam.set(recorder.latitude.current,recorder.longitude.current, recorder.altitude.current, ge.ALTITUDE_ABSOLUTE, recorder.heading.current,recorder.pitch.current,recorder.roll.current);
    ge.getView().setAbstractView(myCam);    
}

function handleGetCamera(){
    var myCam = ge.getView().copyAsCamera(ge.ALTITUDE_ABSOLUTE);
    return myCam;
}


function toggleFullScreen(){
    if (!placeMaking){
        if (fullScreenState == true) {makeNormalScreen();}
        else {makeFullScreen();}
        myExplorer.targetHeadTilt.set(-15);
        freeze();
    }
}

function setViewChange(){
    currentCam = ge.getView().copyAsCamera(ge.ALTITUDE_ABSOLUTE);
    compassIndicator.setRotation(currentCam.getHeading());
    if (placeMaking){
        document.getElementById('your_link').value = getPlaceURL();
        linkChanged();
    }
}

function toggleOverlays(){
    showOverlays = !showOverlays;
    if (showOverlays) {
        cardText.setVisibility(!exploring && !tourPlaying);
        compassIndicator.setVisibility(true);
        compassGauge.setVisibility(true);
        fullScreenIcon.setVisibility(!fullScreenState);
        noFullScreenIcon.setVisibility(fullScreenState);
        keys.setVisibility(true);
        ge.getOptions().setStatusBarVisibility(true);
        ge.getNavigationControl().setVisibility(ge.VISIBILITY_HIDE);
    }
    else {
        cardText.setVisibility(false);
        compassIndicator.setVisibility(false);
        compassGauge.setVisibility(false);
        fullScreenIcon.setVisibility(false);
        noFullScreenIcon.setVisibility(false);
        keys.setVisibility(false);
        ge.getOptions().setStatusBarVisibility(false);
        ge.getNavigationControl().setVisibility(ge.VISIBILITY_HIDE);
    }   
}

function makeFullScreen(){
    if (!fullScreenState){
    	//hide adverts specially for Chrome
    	document.getElementById('notge').style.display = 'none';
    	document.getElementById('headerplaces').style.display = 'none';
        document.getElementById('footeradvert').style.display = 'none';
    	document.getElementById('rightcolumn').style.display = 'none';
    	document.getElementById('footeradvert').style.display = 'none';
    	document.getElementById('footer').style.display = 'none';
    	document.getElementById('signoff').style.display = 'none';
    	var container = document.getElementById('map3d');
    	container.className ="container-fullscreen";
    	fullScreenState = true;
    	noFullScreenIcon.setVisibility(fullScreenState);
    	fullScreenIcon.setVisibility(!fullScreenState);
    	toNormalTextIcon.setVisibility(fullScreenState);
    	toNormalTextTimeout = 4;
    	window.focus();
   	}
}

function makeNormalScreen(){
    if (fullScreenState){
    	document.getElementById('notge').style.display = '';
    	document.getElementById('headerplaces').style.display = '';
        document.getElementById('footeradvert').style.display = '';
    	document.getElementById('rightcolumn').style.display = '';
    	document.getElementById('footeradvert').style.display = '';
    	document.getElementById('footer').style.display = '';
    	document.getElementById('signoff').style.display = '';
    	var container = document.getElementById('map3d');
    	container.className ="container";
    	fullScreenState = false;
    	noFullScreenIcon.setVisibility(fullScreenState);
    	fullScreenIcon.setVisibility(!fullScreenState);
    	toNormalTextIcon.setVisibility(fullScreenState);
   	}
}

function toggleMap(){
    if (mapVisible){
        document.getElementById('map').style.display = "none";
        document.getElementById('mapbtn').src='showmap.png';
        //document.getElementById('toggleMapLink').innerHTML = "Show map";
        mapVisible = false;
    }
    else{
        document.getElementById('map').style.display = "";
        map.checkResize();     
        document.getElementById('mapbtn').src='hidemap.png';
        //document.getElementById('toggleMapLink').innerHTML = "Hide map";
        mapVisible = true;
    }
  
}

function exploreobject(object){
    	if (object && object.hasChildNodes()) {
		var childNodes = object.getChildNodes();
		var numChildNodes = childNodes.getLength();
		for (var i = 0; i < numChildNodes; i++) {
			var child = childNodes.item(i);
			if (!exploreobject(child))
			          return false;
			}
	return true;
	}
}

function setMouseUp(event){
    mouseClickAge = 0;
    var handledClick = false;
    var INSET_PIXELS_X = document.getElementById("map3d").offsetWidth - event.getClientX();
    var INSET_PIXELS_Y = event.getClientY();
    var PIXELS_Y = document.getElementById("map3d").offsetHeight - event.getClientY();
       
    //click in fullscreen area
    if (INSET_PIXELS_X < 32 && handledClick == false && (exploring || tourPlaying)){
        if (INSET_PIXELS_Y < 32){
            toggleFullScreen();
            handledClick = true;
        }
    }

    if (!clickToExplore.getVisibility() && tourPlaying && handledClick == false){
        setExplorer();
        handledClick = true;       
    }
      
 
     //spash click to start
    if (!exploring && !placeMaking && handledClick == false){
        playPlace();
        mouseClickAge = mousePauseDuration - 1;
        handledClick = true;
    }

  
    //click help
    if (event.getButton() == 0){
        if (showHelp == 0 && event.getClientY() < 20 && event.getClientX() > 310 && event.getClientX() < 360 && handledClick == false){
            showHelp = 1;
            helpSwivel.target = 0;
            noMoveTimeOut = -1;
            handledClick = true;
        }
        if (showHelp == 2 && event.getClientX() < 228 && handledClick == false){
            showHelp = 3;
            helpSwivel.target = 90;
            handledClick = true;
        }
    }
      
    //click to lock view
    if (handledClick == false){     
        setExplorerToCam();
    }
    
    if (handledClick){
        event.preventDefault();
    } 
    mouseIsDown = false;
}

function setMouseDown(event){
    //currentCam = ge.getView().copyAsCamera(ge.ALTITUDE_ABSOLUTE);
    mouseIsDown = true;
    windowFocusDone = false;
    if (placeMaking){overlaysState(false);}
    freeze();
    //mouseClickAge = 0;
}

function setMouseMove(event){
    if (mouseClickAge > mousePauseDuration && (exploring || recorder.recording || recordCountDown > -1) && myExplorer.height.target < 100000){ 
        mouseX = ((event.getClientX() / document.getElementById("map3d").offsetWidth)-0.5)*2;
        if (mouseX > 0){
            spin = (mouseX * mouseX)*250;
        }
        else {
            spin = (-mouseX * mouseX)*250;
        }
        //spin = ((event.getClientX() / document.getElementById("map3d").offsetWidth) - 0.5)*360;
        mouseY = ((event.getClientY() / document.getElementById("map3d").offsetHeight) - 0.5) * 2;
        if (mouseY > 0){
            myExplorer.targetHeadTilt.target = (-mouseY * mouseY)*90;
        }
        else {
            myExplorer.targetHeadTilt.target = (mouseY * mouseY) * 90;
        }
        mouseMoveAge = 0;
    }
}

function showTypeName(node, arguments){
    alert(node.getType());
}

function updateLow(deltaTime){
    //stuff
}

function getLookAtData(){
    if (recorder.duration > 0) {recorder.initFrame(0); setExplorerToCam();}
    var myCam = ge.getView().copyAsLookAt(ge.ALTITUDE_ABSOLUTE);
    var myData = '';
    myData += myExplorer.latitude;
    myData += ','+ myExplorer.longitude;
    myData += ',' + myExplorer.height.current;
    myData += ',' + myExplorer.heading.current;
    myData += ',' + (myCam.getTilt()-90);
    myData += ',' + myExplorer.defaultSpeedFactor;
    if (myCard.imageId > 999){ myCard.imageId = 0 }
    myData += ',' + myCard.imageId;
    myData += ',' + recorder.duration;
    if (myCard.kmzUrl != undefined){
       myData += ',' + myCard.kmzUrl; 
    }
    return myData;
}

function toggleRecording(){
    if (recorder.recording || recordCountDown> -1){
        recordCountDown = -1;
        setNumberIcon(0);
        recorder.stopRecording(); 
        //initialise to start of recording
        recorder.initFrame(0);
    }
    else {
        if (!exploring){playPlace();}
        document.getElementById('recordbtn').src = 'finishtour.png';
        overlaysState(false);
        previousTextBtnDisabled(true);
        nextTextBtnDisabled(true);        
        //start count down
        recordCountDown = 4;
        noMoveTimeOut = -1;
    }
}

function togglePlayback(){
    if (recorder.playing){
        document.getElementById('playbtn').src = 'play.png';
        recorder.stopPlayback();      
    }
    else {
        if (!exploring){playPlace();}
        document.getElementById('playbtn').src = 'stop.png';
        //var mystuff = wrapKml(recorder.asKml());
        //document.getElementById('kmldata').value = mystuff;      
        recorder.startPlayback();
        //var tour = ge.parseKml(mystuff);
        //ge.getTourPlayer().setTour(tour);  


    }
}

function setNumberIcon(value){
    switch(value){
        case 0: {oneIcon.setVisibility(false); twoIcon.setVisibility(false); threeIcon.setVisibility(false); fourIcon.setVisibility(false); break; }
        case 1: {oneIcon.setVisibility(true); twoIcon.setVisibility(false); threeIcon.setVisibility(false); fourIcon.setVisibility(false); break; }
        case 2: {oneIcon.setVisibility(false); twoIcon.setVisibility(true); threeIcon.setVisibility(false); fourIcon.setVisibility(false); break; }
        case 3: {oneIcon.setVisibility(false); twoIcon.setVisibility(false); threeIcon.setVisibility(true); fourIcon.setVisibility(false); break; }
        case 4: {oneIcon.setVisibility(false); twoIcon.setVisibility(false); threeIcon.setVisibility(false); fourIcon.setVisibility(true); break; }
    }
}

function shareBtnDisabled(value){
    if (value){
        document.getElementById('sharebtn').onclick = null;
        document.getElementById('sharebtn').src = 'sharethisplace_off.png';
        document.getElementById('sharebtn').style.cursor = 'default'; 
    }
    else{
        document.getElementById('sharebtn').onclick = saveCard;
        document.getElementById('sharebtn').src = 'sharethisplace.png';
        document.getElementById('sharebtn').style.cursor = 'pointer'; 
    }    
}

function recordBtnDisabled(value){
    if (value){
        document.getElementById('recordbtn').onclick = null;
        document.getElementById('recordbtn').src = 'recordtour_off.png';
        document.getElementById('recordbtn').style.cursor = 'default'; 
    }
    else{
        document.getElementById('recordbtn').onclick = toggleRecording;
        document.getElementById('recordbtn').src = 'recordtour.png';
        document.getElementById('recordbtn').style.cursor = 'pointer'; 
    }    
}

function mapBtnDisabled(value){
    if (value){
        document.getElementById('mapbtn').onclick = null;
        document.getElementById('mapbtn').src = 'showmap_off.png';
        document.getElementById('mapbtn').style.cursor = 'default'; 
    }
    else{
        document.getElementById('mapbtn').onclick = toggleMap;
        document.getElementById('mapbtn').src = 'showmap.png';
        document.getElementById('mapbtn').style.cursor = 'pointer'; 
    }  
}

function navBtnDisabled(value){
    if (value){
        document.getElementById('navbtn').onclick = null;
        document.getElementById('navbtn').src = 'takecontrol_off.png';
        document.getElementById('navbtn').style.cursor = 'default';
    }
    else{
        document.getElementById('navbtn').onclick = setExplorer;
        document.getElementById('navbtn').src = 'takecontrol.png';
        document.getElementById('navbtn').style.cursor = 'pointer';
    }  
}

function playBtnDisabled(value){
    if (value){
        document.getElementById('playbtn').onclick = null;
        document.getElementById('playbtn').src = 'play_off.png';
        document.getElementById('playbtn').style.cursor = 'default';
    }
    else{
        document.getElementById('playbtn').onclick = togglePlayback;
        document.getElementById('playbtn').src = 'play.png';
        document.getElementById('playbtn').style.cursor = 'pointer';
    }  
}

function nextTextBtnDisabled(value){
    if (value){
        document.getElementById('nextTextBtn').onclick = null;
        document.getElementById('nextTextBtn').src = 'next_off.png';
        document.getElementById('nextTextBtn').style.cursor = 'default';
    }
    else{
        document.getElementById('nextTextBtn').onclick = decCardText;
        document.getElementById('nextTextBtn').src = 'next.png';
        document.getElementById('nextTextBtn').style.cursor = 'pointer';
    }  
}

function previousTextBtnDisabled(value){
    if (value){
        document.getElementById('previousTextBtn').onclick = null;
        document.getElementById('previousTextBtn').src = 'previous_off.png';
        document.getElementById('previousTextBtn').style.cursor = 'default';
    }
    else{
        document.getElementById('previousTextBtn').onclick = decCardText;
        document.getElementById('previousTextBtn').src = 'previous.png';
        document.getElementById('previousTextBtn').style.cursor = 'pointer';
    }  
}

function moveexplorer() {
    //measure frame time so animation is frame independant
    now = (new Date()).getTime();
    var deltaTime = (now - lastMill) / 1000.0;
    lastMill = now;
    mouseMoveAge += deltaTime;
    if (!mouseIsDown){
        mouseClickAge += deltaTime;
    }
   
    if (!windowFocusDone && mouseClickAge > mousePauseDuration){ window.focus(); ge.getWindow().blur(); windowFocusDone = true;}   
    updateMousePause(deltaTime);
   
    if (fullScreenState && toNormalTextIcon.getVisibility()){
        if (toNormalTextTimeout < 0){toNormalTextIcon.setVisibility(false);}
        else {toNormalTextTimeout -= deltaTime;}
    }

    if (recordCountDown > -1){
        recordCountDown -= deltaTime;
        if (recordCountDown > 3){ setNumberIcon(4);}
        else if (recordCountDown > 2){ setNumberIcon(3);}
        else if (recordCountDown > 1){ setNumberIcon(2);}
        else if (recordCountDown > 0){ setNumberIcon(1);}
        else if (recordCountDown < 0){
            setNumberIcon(0);
            recordCountDown = -1;
            recordingIcon.setVisibility(true);
            recorder.startRecording();  
        }
    }

    if (lowUpdate > 10 && exploring && !placeMaking){ updateLow(lowUpdate); lowUpdate = 0;}
    recorder.update(deltaTime);

    updateHelp(deltaTime);
   
    lowUpdate += deltaTime;
    //compassIndicator.setRotation(currentCam.getHeading());  //myExplorer.heading.current //currentCam.getHeading()

    if (downKey) { myExplorer.speedFactor.target = -myExplorer.targetSpeedFactor}
    else if (upKey) { myExplorer.speedFactor.target = myExplorer.targetSpeedFactor}
    else {myExplorer.speedFactor.target = 0;}
    myExplorer.heading.target += spin * deltaTime * 0.3;
    spin -= spin * deltaTime * 0.2;
    
    if (mouseMoveAge > 3){spin -= spin * deltaTime * 0.8;}
    else {spin -= spin * deltaTime * 0.2;}
    
    //heading

    if (sideLeftKey) { myExplorer.strafeFactor.target = -myExplorer.targetSpeedFactor}
    else if (sideRightKey) { myExplorer.strafeFactor.target = myExplorer.targetSpeedFactor}
    else if (zKey || mouseMoveAge < 3){
        if (leftKey) { myExplorer.strafeFactor.target = -myExplorer.targetSpeedFactor}
        else if (rightKey) { myExplorer.strafeFactor.target = myExplorer.targetSpeedFactor}
        else {myExplorer.strafeFactor.target = 0;}           
    }
    else {myExplorer.strafeFactor.target = 0;} 


    if (mouseMoveAge > 3 && !zKey){
        if (leftKey) { myExplorer.heading.target -= 30 * deltaTime}
        else if (rightKey){ myExplorer.heading.target += 30 * deltaTime }
    }

    //altitude
    if (shiftKey && myExplorer.height.target < 100000) {
        myExplorer.height.target += (0.1 + myExplorer.height.target - myExplorer.groundAltitude) * deltaTime * myExplorer.targetSpeedFactor/2
    }
    else if (ctrlKey){
        myExplorer.height.target -= (myExplorer.height.target - myExplorer.groundAltitude) * deltaTime * myExplorer.targetSpeedFactor/2
    }

    //speed
    if (spaceKey) { myExplorer.targetSpeedFactor = myExplorer.defaultSpeedFactor * 4}
    else {myExplorer.targetSpeedFactor = myExplorer.defaultSpeedFactor;}

    //cockpit
    //cockpit.getOverlayXY().setY(0.5 - myExplorer.targetHeadTilt.current/70);
    //cockpit.getOverlayXY().setY(0.5 - (currentCam.getTilt()-90)/40); 

    if (mapVisible && fullScreenState==false){ map.setCenter(new GLatLng(myExplorer.latitude, myExplorer.longitude)); }

    if (doFreeze){freeze();}

    if ((recorder.recording || recordCountDown > -1 || exploring) && mouseClickAge > mousePauseDuration){
        myExplorer.update(deltaTime); 
        updateView(deltaTime);
    }

}

function updateHelp(deltaTime){
    if (exploring && noMoveTimeOut > -1){ 
        noMoveTimeOut -= deltaTime;
        if (noMoveTimeOut < 0){
            showHelp = 1;
            helpSwivel.target = 0;
            noMoveTimeOut = -1;           
        }
    }
    if (showHelp == 1){
        helpSwivel.update(deltaTime);
        keys.setRotation(helpSwivel.current);
        if (helpSwivel.current < 5){
            helpSwivel.set(0);
            keys.setRotation(0);
            showHelp = 2;
        }  
    }
    if (showHelp == 3){
        helpSwivel.update(deltaTime)
        keys.setRotation(helpSwivel.current);
        if (helpSwivel.current > 85){
            helpSwivel.set(90);
            keys.setRotation(90);
            showHelp = 0;
        }  
    }
}

function saveCard(){
        recorder.name = myCard.name;
        recorder.address = getLookAtData();
        document.getElementById("kmladdress").value = getLookAtData();
        recorder.description = ''; //myCard.description; //users don't get to keep the description for their own cards
        document.getElementById("kmldata").value = '<![CDATA[' + recorder.asPlayList() + ']]>'; 
        document.getElementById("saveForm").submit();
}

function setExplorerToCam(){
    currentCam = ge.getView().copyAsCamera(ge.ALTITUDE_ABSOLUTE);
    myExplorer.latitude = currentCam.getLatitude();
    myExplorer.longitude = currentCam.getLongitude();
    myExplorer.height.set(currentCam.getAltitude());
    myExplorer.heading.set(currentCam.getHeading());
    myExplorer.targetHeadTilt.set(currentCam.getTilt()-90);
    freeze();
}

function setExplorerToRecorder(){
    currentCam = ge.getView().copyAsCamera(ge.ALTITUDE_ABSOLUTE);
    myExplorer.latitude = recorder.latitude.current;
    myExplorer.longitude = recorder.longitude.current;
    myExplorer.height.set(recorder.altitude.current);
    myExplorer.heading.set(recorder.heading.current);
    myExplorer.targetHeadTilt.set(recorder.pitch.current);
    freeze();
}

function setGoogleView(){
    ge.getNavigationControl().setVisibility(ge.VISIBILITY_SHOW);
    currentCam = ge.getView().copyAsCamera(ge.ALTITUDE_ABSOLUTE);
    ge.getView().setAbstractView(currentCam);
}

function updateView(deltaTime){
    currentCam = ge.getView().copyAsCamera(ge.ALTITUDE_ABSOLUTE);
    if (mouseIsDown == false){
        currentCam.set(myExplorer.latitude,myExplorer.longitude, myExplorer.height.current, ge.ALTITUDE_ABSOLUTE, myExplorer.heading.current,90 + myExplorer.targetHeadTilt.current,myExplorer.roll);
    }
    ge.getView().setAbstractView(currentCam);
}

function toggleBuildings(){
  toggleBuildingsState = !toggleBuildingsState;
  ge.getLayerRoot().enableLayerById(ge.LAYER_BUILDINGS, toggleBuildingsState);
}

function toggleGrayBuildings(){
  toggleGrayBuildingsState = !toggleGrayBuildingsState;
  ge.getLayerRoot().enableLayerById(ge.LAYER_BUILDINGS_LOW_RESOLUTION, toggleGrayBuildingsState);
}

function toggleBorders(){
  toggleBordersState = !toggleBordersState;
  ge.getLayerRoot().enableLayerById(ge.LAYER_BORDERS, toggleBordersState);
}

function keyDown(event) {
if (textInputFocus == true) {return true; exit;};
    if (!event) {
        event = window.event;
    }
    switch(event.keyCode){
        case 16:           {shiftKey = true; returnValue = false; break; }//shift
        case 17:           {ctrlKey = true; returnValue = false; break; }//CTRL
        case 18:           {altKey = true; returnValue = false; break; }//ALT
        case 20:           {capsKey = true; returnValue = false; break; }//CAPS
        case 27:           {if (fullScreenState){makeNormalScreen();}else{resetPlace();} event.returnValue = false; break;} //ESCAPE
        case 32: case 88:  {spaceKey = true; returnValue = false; stopDef(event); returnValue = false; break; }//SPACE or X for Boost
        case 37: case 65:  {leftKey = true; noMoveTimeOut = -1; event.returnValue = false; break;} //left A
        case 39: case 68:  {rightKey = true; noMoveTimeOut = -1; event.returnValue = false; break;} //right D
        case 38: case 87:  {upKey = true; noMoveTimeOut = -1; event.returnValue = false; break;} //up W
        case 40: case 83:  {downKey = true; noMoveTimeOut = -1; event.returnValue = false; break;} //down S
        case 66: case 98:  {toggleBuildings(); returnValue = false; break;}//B for toggle Buildings
        case 71: case 103: {toggleGrayBuildings(); returnValue = false; break;}//G to toggle Gray Buildings
        case 76: case 108: {toggleBorders(); returnValue = false; break;}//L for toggle borders and labels        
        case 80:           {mouseClickAge = 0; returnValue = false; break;}//P to restart Mouse Pause
        case 90:           {zKey = true; returnValue = false; break; }//Z
        case 115:          {toggleOverlays(); stopDef(event); event.returnValue = false; break; }//F4
        case 188:          {sideLeftKey = true; event.returnValue = false; break;} //left side step <
        case 190:          {sideRightKey = true; event.returnValue = false; break;} //right side step >
        default: return true;
    }
    mouseIsDown = false;
    return false;
}

function stopDef(e) {
    if (e &&e.preventDefault) e.preventDefault();
    else if (window.event && window.event.returnValue)
    event.cancelBubble = true;
    event.stopPropagation();    
    window.eventReturnValue = false;
}

function keyUp(event) {
if (textInputFocus == true) {return true; exit;};
    if (!event) {
        event = window.event;
    }
    
    switch(event.keyCode){
        case 16:           {shiftKey = false; returnValue = false; break; }//shift
        case 17:           {ctrlKey = false; returnValue = false; break; }//CTRL
        case 18:           {altKey = false; returnValue = false; break; }//ALT
        case 20:           {capsKey = false; returnValue = false; break; }//CAPS
        case 32:           {spaceKey = false; returnValue = false; break; }//SPACE
        case 37: case 65:  {leftKey = false; event.returnValue = false; break;} //left A
        case 39: case 68:  {rightKey = false; event.returnValue = false; break;} //right D
        case 38: case 87:  {upKey = false; event.returnValue = false; break;} //up W
        case 40: case 83:  {downKey = false; event.returnValue = false; break;} //down S
        case 90:           {zKey = false; returnValue = false; break; }//Z
        case 188:          {sideLeftKey = false; event.returnValue = false; break;} //left side step <
        case 190:          {sideRightKey = false; event.returnValue = false; break;} //right side step >        
        default: return true;
    }
    mouseIsDown = false;
    return false;
}

function getPlaceURL(){
    return document.location.protocol +'//'+ document.location.host + document.location.pathname + '?cd=' + qs.get("cd") + '&col=' + collection;
}

function updateTitle(textValue){
    myCard.name = unescape(textValue);
    setViewChange();
	document.getElementById("placetitle").innerHTML = '&nbsp;' + myCard.name;
    linkChanged();
}

function togglePlaceMaker(){
    placeMaking = !placeMaking;
    if (placeMaking){   
        ge.getTourPlayer().setTour(null);  
        if (myCard.imageId > 999){
            setCardImage(0);
        }
        if (mapVisible) { toggleMap() }
        mapBtnDisabled(true);
        navBtnDisabled(true);
        document.getElementById("gallery").checked = false;
        document.getElementById("placetitle").innerHTML = '&nbsp;' + document.getElementById("friend_nam").value;
        overlaysState(true);
        exploring = false;
        document.getElementById('placebtn').src = 'closeplacemaker.png';
        document.getElementById('sendplace').style.display = '';
    }
    else
    {
        mapBtnDisabled(false);
        navBtnDisabled(false);
        recorder.stopRecording();
        recorder.stopPlayback();
        //if data is recorded then initialise to first frame else restart card
        if (recorder.recordingIndex > 0){
            recorder.initFrame(0);
        }
        else{
            initPlace();
        }        
        document.getElementById("placebtn").src = 'openplacemaker.png';
        document.getElementById('sendplace').style.display = 'none';
    }
}

