var GarminDeviceControlDemo = Class.create();
GarminDeviceControlDemo.prototype = {

	initialize: function(statusDiv, mapId) {        
        this.status = $(statusDiv);
        this.mc = new Garmin.MapController(mapId);
        
        this.findDevicesButton = $("findDevicesButton");
        this.cancelFindDevicesButton = $("cancelFindDevicesButton");
        this.deviceSelect = $("deviceSelect");
        this.deviceInfo = $("deviceInfoText");

        this.readDataButton = $("readDataButton");
        this.cancelReadDataButton = $("cancelReadDataButton");
        this.readTracksText = $("readTracksText");
        this.readTracksSelect = $("readTracksSelect");
        this.readWaypointsSelect = $("readWaypointsSelect");

        this.writeDataButton = $("writeDataButton");
        this.cancelWriteDataButton = $("cancelWriteDataButton");
        this.writeDataSelect = $("writeDataSelect");
		this.writeDataText = $("writeDataText");
		this.writeDataFilename = $("writeDataFilename");

		this.progressBar = $("progressBar");
		this.progressBarDisplay = $("progressBarDisplay");

		this.garminController = null;
        this.tracks = null;
		this.intializeController();

		if(this.garminController && this.garminController.isPluginInitialized()) {
	        this.findDevicesButton.disabled = false;
	        this.findDevicesButton.onclick = function() {
	        	this.findDevicesButton.disabled = true;
	        	this.cancelFindDevicesButton.disabled = false;
	        	this.garminController.findDevices();
	        }.bind(this)
		}
	},
	
	intializeController: function() {
		try {
			this.garminController = new Garmin.DeviceControl();
			this.garminController.register(this);
			
			if(this.garminController.unlock("file:///C:/dev/","bd04dc1f5e97a6ff1ea76c564d133b7e")) {
	        	this.setStatus("Plug-in initialized.  Find some devices to get started.");
			} else {
	        	this.setStatus("The plug-in was not unlocked successfully.");
			}
        } catch (e) {
            this.setStatus(e.message);
//            if(e.name == "OutOfDatePluginException") {
//	        	this.setStatus("Your plug-in is out of date.  Please update.");
//            } else if(e.name == "PluginNotInstalledException") { 
//	        	this.setStatus("You'll need to install the Garmin Communicator Plug-In to connect to a device.");
//            } else if(e.name == "BrowserNotSupportedException") { 
//	        	this.setStatus("Your browser is not supported to  use the Garmin Communicator Plug-In.");
//            } else {
//	        	this.setStatus("There was a problem initializing the Garmin Communicator Plug-In.");
//            }
        }
	},

	showProgressBar: function() {
		Element.show(this.progressBar);
	},

	hideProgressBar: function() {
		Element.hide(this.progressBar);
	},

	updateProgressBar: function(value) {
		var percent = (value <= 100) ? value : 100;
	    this.progressBarDisplay.style.width = percent + "%";
	},

    onStartFindDevices: function(json) {
        this.setStatus("Looking for connected Garmin devices");
    },

    onFinishFindDevices: function(json) {
       	this.findDevicesButton.disabled = false;
       	this.cancelFindDevicesButton.disabled = true;

        if(json.controller.numDevices > 0) {
            var devices = json.controller.getDevices();
            this.setStatus("Found " + devices.length + " devices.");

			this.listDevices(devices);
			
	        this.cancelReadDataButton.onclick = function() {
	        	this.readDataButton.disabled = false;
	        	this.cancelReadDataButton.disabled = true;
	        	this.hideProgressBar();
	        	this.garminController.cancelReadFromDevice();
	        }.bind(this)
			
	        this.readDataButton.disabled = false;
	        this.readDataButton.onclick = function() {
	        	this.readDataButton.disabled = true;
	        	this.cancelReadDataButton.disabled = false;
	        	this.showProgressBar();
	        	this.garminController.readFromDevice();
	        }.bind(this)


	        this.writeDataSelect.disabled = false;
			this.writeDataSelect.onchange = function() {
				this.loadWriteData(this.writeDataSelect.value);
			}.bind(this)
			this.loadWriteData(this.writeDataSelect.value);

	        this.cancelWriteDataButton.onclick = function() {
	        	this.writeDataButton.disabled = false;
	        	this.cancelWriteDataButton.disabled = true;
	        	this.hideProgressBar();
	        	this.garminController.cancelWriteToDevice();
	        }.bind(this)

	        this.writeDataButton.disabled = false;	        
	        this.writeDataButton.onclick = function() {
	        	this.writeDataButton.disabled = true;
	        	this.cancelWriteDataButton.disabled = false;
	        	this.showProgressBar();
	        	this.garminController.writeToDevice(this.writeDataText.value, this.writeDataFilename.value);
	        }.bind(this);
        } else {
			this.setStatus("No devices found.");
        }
    },

	onCancelFindDevices: function(json) {
    	this.setStatus("Find cancelled");
    },

	listDevices: function(devices) {
		for( var i=0; i < devices.length; i++ ) {
           	this.deviceSelect.options[i] = new Option(devices[i].getDisplayName(),devices[i].getNumber());
           	if(devices[i].getNumber() == this.garminController.deviceNumber) {
           		this.deviceSelect.selectedIndex = i;
           		this.showDeviceInfo(devices[i]);
           	}
		}
		this.deviceSelect.onchange = function() {
			var device = this.garminController.getDevices()[this.deviceSelect.value];
			this.showDeviceInfo(device);
		
			this.garminController.setDeviceNumber(this.deviceSelect.value);
		}.bind(this)
		this.deviceSelect.disabled = false;
	},

	showDeviceInfo: function(device) {
		this.deviceInfo.innerHTML = "Part Number:\t\t" + device.getPartNumber() + "\n";
		this.deviceInfo.innerHTML += "Software Version:\t" + device.getSoftwareVersion() + "\n";
		this.deviceInfo.innerHTML += "Description:\t\t" + device.getDescription() + "\n";
		this.deviceInfo.innerHTML += "Id:\t\t\t" + device.getId();
	},

    onProgressReadFromDevice: function(json) {
	  	this.updateProgressBar(json.progress.getPercentage());
    	this.setStatus(json.progress);
    },
    
	onCancelReadFromDevice: function(json) {
    	this.setStatus("Read cancelled");
    },

    onFinishReadFromDevice: function(json) {
       	this.readDataButton.disabled = false;
       	this.cancelReadDataButton.disabled = true;
	    this.hideProgressBar();
    	this.setStatus("Data read from device.");

    	var gpsData = json.controller.gpsData;
    	
    	this.setStatus("Parsing track data...");
    	var factory = new Garmin.GpsDataFactory();
    	factory.parseGpxDocument(gpsData);
		this.tracks = factory.getTracks();
		this.waypoints = factory.getWaypoints();
    	this.setStatus(this.tracks.length + " tracks and " + this.waypoints.length + " waypoints found");
    	
    	this.listTracks(this.tracks);
    	this.listWayPoints(this.waypoints);
    },
    
    listTracks: function(tracks) {
    	this.clearTracks();
		for( var i=0; i < tracks.length; i++ ) {
			var trk = tracks[i];
			if(trk.isDrawable()) {
	           	this.readTracksSelect.options[i] = new Option(trk.getStartDate().getDateString() + " - (" + trk.getDuration() + ")",i);
	        }
		}
		this.displayTrack(tracks[this.readTracksSelect.selectedIndex]);
		this.readTracksSelect.onchange = function() {
			var trk = this.tracks[this.readTracksSelect.selectedIndex];
			this.displayTrack(trk);
		}.bind(this)
		this.readTracksSelect.disabled = false;
    },
    
    listWayPoints: function(waypoints) {
    	this.clearWayPoints();
		for( var i=0; i < waypoints.length; i++ ) {
			var wpt = waypoints[i];
	        this.readWaypointsSelect.options[i] = new Option(wpt.getName(),i);
		}
		this.readWaypointsSelect.onchange = function() {
			var wpt = this.waypoints[this.readWaypointsSelect.selectedIndex];
			this.displayWayPoint(wpt);
		}.bind(this)
		this.readWaypointsSelect.disabled = false;
    },
    
    clearTracks: function() {
		for( var i=0; i < this.readTracksSelect.options.length; i++ ) {
           	this.readTracksSelect.options[i] = null;
		}
    },

    clearWayPoints: function() {
		for( var i=0; i < this.readWaypointsSelect.options.length; i++ ) {
           	this.readWaypointsSelect.options[i] = null;
		}
    },

    
    displayTrack: function(track) {
		this.mc.map.clearOverlays();
        this.mc.centerAndScale(track.getStartLat(), track.getStartLng());
        this.mc.addTrack(track);
    },

    displayWayPoint: function(wpt) {
		this.mc.map.clearOverlays();
        this.mc.centerAndScale(wpt.getLat(), wpt.getLng());
        this.mc.addWayPoint(wpt);
    },

	loadWriteData: function(filepath) {
		new Ajax.Request(filepath, {
			onSuccess: function(resp) {
				this.writeDataText.innerHTML = resp.responseText;
			}.bind(this),
			onFailure: function(resp) {
				alert("Error deleting all pending activities");
			}
		});
	},

    onStartWriteToDevice: function(json) { 
    	this.setStatus("Writing data to to the device");
    },

    onCancelWriteToDevice: function(json) { 
    	this.setStatus("Writing cancelled");
    },

    /**
     * The device already has a file with this name on it.  Do we want to override?  1 is yes, 2 is no
     */ 
    onWaitingWriteToDevice: function(json) { 
        if(confirm(json.message.getText())) {
            this.setStatus('Overwriting file');
            json.controller.respondToMessageBox(true);
        } else {
            this.setStatus('Will not be overwriting file');
            json.controller.respondToMessageBox(false);
        }
    },

    onProgressWriteToDevice: function(json) {
	  	this.updateProgressBar(json.progress.getPercentage());
    	this.setStatus(json.progress);
    },

    onFinishWriteToDevice: function(json) {
	    this.hideProgressBar();
    	this.setStatus("Data written to the device.");
	    this.hideProgressBar();
       	this.writeDataButton.disabled = false;
       	this.cancelWriteDataButton.disabled = true;
    },

    onException: function(json) {
	    alert("Exception: " + json.msg.message);
    },

	setStatus: function(statusText) {
	    this.status.innerHTML = statusText;
	}
};