/**
 * Copyright © 2007 Garmin Ltd. or its subsidiaries.
 *
 * Licensed under the Apache License, Version 2.0 (the 'License')
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an 'AS IS' BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 * 
 * @fileoverview GarminDeviceControlDemo Demonstrates Garmin.DeviceControl.
 * 
 * @author Diana Chow diana dot chow at garmin dot com
 * @version 1.0
 */
var GarminFirmwareUpdateControlDemo = Class.create();
GarminFirmwareUpdateControlDemo.prototype = {

	initialize: function(statusDiv, keysArray) {        
        this.status = $(statusDiv);
        this.keys = keysArray;
        
        this.findDevicesButton = $("findDevicesButton");
        this.cancelFindDevicesButton = $("cancelFindDevicesButton");
        this.deviceSelect = $("deviceSelect");
        this.deviceInfo = $("deviceInfoText");

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

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

		this.garminController = null;
		this.intializeController();
		
		this.garminController.gpsDataType = Garmin.DeviceControl.FILE_TYPES.firmware;
		
		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(this.keys)) {
	        	this.setStatus("Plug-in initialized.  Find some devices to get started.");
			} else {
	        	this.setStatus("The plug-in was not unlocked successfully.");
	        	this.garminController = null;
			}
		} catch (e) { this.handleException(e); }
	},

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

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

	updateProgressBar: function(value) {
		if (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) {
    	try {
	       	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.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();
					
					try {
					    // Leave as specific type calls in order to test both generic and specific
						switch(this.garminController.gpsDataType) {
							case Garmin.DeviceControl.FILE_TYPES.firmware:
								this.garminController.downloadFirmwareToDevice(this.writeDataText.value);
								break;
						}
					} catch (e) { this.handleException(e); }
					
		        }.bind(this);

	        } else {
				this.setStatus("No devices found.");
				this.deviceInfo.innerHTML = "";
				this._clearHtmlSelect(this.deviceSelect);
				this.deviceSelect.disabled = true;
	        }
    	} catch (e) { this.handleException(e); }
    },
    
	onCancelFindDevices: function(json) {
    	this.setStatus("Find cancelled");
    },

	listDevices: function(devices) {
		this._clearHtmlSelect(this.deviceSelect);
		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.selectedIndex = 0;
       	this.showDeviceInfo(devices[0]);
		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() + "\n\n";
		
		var dataTypes = device.getDeviceDataTypes().values();		
		var typeListSize = dataTypes.length;
		for (var i = 0; i < typeListSize; i++) {
			this.deviceInfo.innerHTML += "-DataType---------------\n"
			this.deviceInfo.innerHTML += "  Name:\t\t" + dataTypes[i].getDisplayName() + "\n";
			this.deviceInfo.innerHTML += "  Extension:\t" + dataTypes[i].getFileExtension() + "\n";
			this.deviceInfo.innerHTML += "  Read:\t\t" + dataTypes[i].hasReadAccess() + "\n";
			this.deviceInfo.innerHTML += "  Write:\t" + dataTypes[i].hasWriteAccess() + "\n\n";			
		}
	},

	/**Sets the size of the select options to zero which essentially clears it from 
	 * any values.
	 * @private
	 */
    _clearHtmlSelect: function(select) {
		if(select) {
			//select.size = 0;
			select.options.size = 0;
		}
    },

	loadWriteData: function(filepath) {
		new Ajax.Request(filepath, {
			onSuccess: function(resp) {
				this.writeDataText.value = resp.responseText;
			}.bind(this),
			onFailure: function(resp) {
				this.handleException(new Error("Error loading test data: "+filepath));
			}.bind(this)
		});
	},

    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) {
	    this.handleException(json.msg);
    },
    
	handleException: function(error) {
		var msg = error.name + ": " + error.message;	
		if (Garmin.PluginUtils.isDeviceErrorXml(error)) {
			msg = Garmin.PluginUtils.getDeviceErrorMessage(error);	
		}
	    this.setStatus(msg);
	    alert(msg);
	},

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