/* Copyright 2009 Palm, Inc.  All rights reserved. */

var label_status_checking = $L('Checking for updates...');
var label_status_upToDate = $L('Your phone is up to date.');
var label_status_appUpDate = $L('Application updates are now available.');
var label_status_noNetwork = $L("Waiting for the network...");
var label_status_failedNetwork = $L("Unable to connect.  Try again later.");
var label_status_failedNetwork_firstuse = $L("Unable to connect.");

var label_button_showUpdates = $L("Show Updates");

var updatesPath = "/usr/palm/applications/com.palm.app.updates";
var updatesResources = updatesPath + "/resources/";

var MainAssistant = Class.create({
    initialize: function(params){
		Mojo.Log.info("Main: initialize ", Object.toJSON(params));
		this.appAssistant = Mojo.Controller.getAppController().assistant;
        this.params = params || {checkForUpdate: true};		
		this.autoUpdate = this.params.autoUpdate || false;
		
		if(this.autoUpdate === true){
			this.firstUseUtils = FirstUseUtil.getUtil();
		}
		
		this.state = "";
		this.oldState = "";
		this.networkAvailable = true;
		this.systemCheckInProgress = false;
		this.appCheckInProgress = false;
		this.failCount = 0;
		this.releaseNotes = null;

    },
		
	$L: function(str){
		if(this.stringTable == null){
			this.stringTable = Mojo.Locale.readStringTable("strings.json", Mojo.Locale.current, updatesResources);
		}
		return Mojo.Locale.localizeString(str, this.stringTable)
	},	
    setup: function(){
	    this.spinner = $("system-spinner");
				
		this.updatesModel = UpdateModel.getModel();
		Mojo.Log.info("Main: setup ", this.updatesModel.getStatus());
		
		this.releaseNotesDiv = this.controller.get('release_notes');		

		this.Depot = UpdatesDepot.getDepot();
		this.controller.serviceRequest('palm://com.palm.preferences', {
				method: 'systemProperties/Get',
				parameters: {"key": "com.palm.properties.version"},
				onSuccess: function(obj){
					if ("com.palm.properties.version" in obj) {
						this.Depot.setCurrentVersion(obj["com.palm.properties.version"]);
						this.Depot.getCurrentReleaseDetails(function(html){
								this.releaseNotes = html;								
								this.releaseNotesDiv.innerHTML = this.releaseNotes;
							}.bind(this)
						);
					}
				}.bind(this)
		    });

        var appMenuModel = {
            visible: true,
            items: [Mojo.Menu.editItem, Mojo.Menu.helpItem]
        };
        this.controller.setupWidget(Mojo.Menu.appMenu, {omitDefaultItems: true}, appMenuModel);
		
		this.cmdMenuModel = {
			visible: false,
			items: [{},{},{
				icon:'sync',
				command: 'checkForUpdates'
			}]
		};		
		this.controller.setupWidget(Mojo.Menu.commandMenu, undefined, this.cmdMenuModel);		
		
		this.appButtonModel = {buttonLabel: label_button_showUpdates};
		this.appButton = this.controller.get('appButton');
        this.controller.setupWidget('appButton', {}, this.appButtonModel);
		Mojo.Event.listen(this.appButton,'mojo-tap', this.appUpdateClickCallback.bindAsEventListener(this));
		
		var request = new Mojo.Service.Request('palm://com.palm.systemservice', {
            method: 'getPreferences',
            parameters: {
                'keys': ['allowIncomingCallsOver2G']
            },
            onSuccess: function(response) {
                if ( response && !Object.isUndefined(response['allowIncomingCallsOver2G']) ) {
					Mojo.Log.info( "Main: allowIncomingCallsOver2G", response['allowIncomingCallsOver2G']);
					AppAssistant.dataBlocksCalls = !response['allowIncomingCallsOver2G'];
                }				
            },
            onFailure: function(r) {
                Mojo.Log.info( "Main: Failure calling palm://com.palm.systemservice/getPreferences with response %j",r);
            }
        });
		
		if (this.autoUpdate === true) { 
			Mojo.Log.info("Details: Show emergency");
			this.controller.document.body.className = "firstuse palm-dark";
			Mojo.Event.listen(this.controller.get('firstuse_emergency'), Mojo.Event.tap, this.onEmergencyTap.bind(this));
			this.keyPressEventHandler =  this.firstUseUtils.handleKeyPressEvent.bind(this);
			this.controller.listen(this.controller.sceneElement, Mojo.Event.keydown, this.keyPressEventHandler);
		}

    },

	onEmergencyTap: function() {
		var labels = [];
		if(this.firstUseUtils.customerCareNumber && this.firstUseUtils.customerCareNumber.length > 0) {
			labels = [{label: $L('Emergency call'), command: 'emergency-call'}, 
					{label: $L('Call customer service'), command: 'customer-care'},
					{label: $L('Cancel'), command: 'cancel'}
			];
		} else {
			labels = [{label: $L('Emergency call'), command: 'emergency-call'},
					{label: $L('Cancel'), command: 'cancel'}
			];
		}

		this.controller.popupSubmenu({
	   		onChoose: function(value) {
				if ( "emergency-call" === value ) {
					this.emergencyDial();
				} else if ("customer-care" === value){
					this.customerCareDial();
				}
			}.bind(this),
	   		placeNear: this.controller.get('firstuse_emergency_menu_anchor'),			
			items: labels
		});
	},

	emergencyDial: function(number) {
		if ( ! number ) {
			number = this.firstUseUtils.emergencyNumbers.first();
		}
		this.firstUseUtils.makeEmergencyCall(number);
	},
	
	customerCareDial: function(number) {
		if ( ! number ) {
			number = this.firstUseUtils.customerCareNumber;
		}
		this.firstUseUtils.callCustomerCare(number);
	},

	

	appUpdateClickCallback: function(){
		var openParams = {
			myapps: ''
		};
		this.controller.serviceRequest('palm://com.palm.applicationManager', {
			method: 'launch',
			parameters: {
				id: 'com.palm.app.findapps',
				params: openParams
			}
		});	
	},
	
    callback: function(payload) {
		Mojo.Log.info("Main: callback " + Object.toJSON(payload));
		if (!("status" in payload)) {
		    return;
		}

		if ("networkAvailable" in payload) {
			if((payload.networkAvailable == true) && (this.networkAvailable == false) && (this.autoUpdate != true)) {
				this.checkIfAppUpdatesAvailable();
			}
		    this.networkAvailable = payload.networkAvailable;
			
		} else {
		    this.networkAvailable = true;
		}

		this.oldState = this.state;
		this.payload = payload;
		this.state = payload.status;
		this.updateState();
    },

    checkButtonCallback: function(event) {

		if (this.networkAvailable == false) {
			var params = {"type":"data", onSuccess: function(event){console.log("connectionsuccess " + Object.toJSON(event))}};
			ConnectionWidget.connect(params, Mojo.Controller.stageController);
		}

		if ( ((this.state == 'UpToDate') || (this.state == 'NetworkFailed')) && (this.networkAvailable == true)) {
			this.checkForUpdates();
		}
    },
	
	checkForUpdates: function() {
		if (this.systemCheckInProgress == false) {
			this.systemCheckInProgress = true;
//****************************************************************************************************************************************************\\
//****************************************************************************************************************************************************\\
//****************************************************************************************************************************************************\\			
			this.updatesModel.checkForUpdates(this.callback.bind(this));
				
			this.setSpinner(true);
			this.controller.get('system-status').innerHTML = $L(label_status_checking);
			this.controller.get('appButton').style.visibility = "hidden";
			this.controller.get('release_notes').style.visibility = "hidden";
			this.controller.get('release_notes').style.display = "none";
			
			if (this.autoUpdate != true) {
				this.checkIfAppUpdatesAvailable();
			}
		}
	},

    updateState: function() {
		Mojo.Log.info('Main: updateState ' + this.state);
	
		if ((this.state == 'Checking') && (this.networkAvailable == false)) {
			this.controller.get('system-status').innerHTML = $L(label_status_noNetwork);
			this.controller.get('release_notes').style.visibility = "hidden";
			this.controller.get('release_notes').style.display = "none";
			var params = {"type":"data", onSuccess: function(event){console.log("connectionsuccess " + Object.toJSON(event))}};
			ConnectionWidget.connect(params, Mojo.Controller.stageController);
			this.setSpinner(false);
		} else if (this.state == 'UpToDate') {
			if (this.autoUpdate === true){  // if this is an autoUpdate then we know that there is an update and we should retry after 5 second wait.
				setTimeout(function(){    
					this.updatesModel.checkForUpdates(this.callback.bind(this));
				}.bind(this), 5000);
				return;
			}

			this.systemCheckInProgress = false;

			if (this.oldState == 'NetworkFailed' && this.networkAvailable == true && this.failCount < 5) {
				Mojo.Log.info('Main: Network is available again, recheck for updates.');
				this.checkForUpdates();
			} else {
				this.failCount = 0;
				if (!this.updateInstalledApps()) {
					this.deviceIsUptoDate();
				}
			}
		} else if (this.state == 'Checking') {
		    this.controller.get('system-status').innerHTML = $L(label_status_checking);
			this.controller.get('release_notes').style.visibility = "hidden";
			this.controller.get('release_notes').style.display = "none";		    
		    this.setSpinner(true);
		} else if (this.state == 'NetworkFailed') {
			this.systemCheckInProgress = false;
			if (this.autoUpdate === true) {
				this.controller.get('system-status').innerHTML = $L(label_status_failedNetwork_firstuse);
			} else {
				this.controller.get('system-status').innerHTML = $L(label_status_failedNetwork);
			}
			this.controller.get('release_notes').style.visibility = "hidden";
			this.controller.get('release_notes').style.display = "none";		    
		    this.setSpinner(false);	
			this.failCount = this.failCount + 1;
		} else if ((this.state == 'Waiting') ||
			   (this.state == 'Download2G') ||
			   (this.state == 'Downloading') ||
			   (this.state == 'DownloadRetry') ||
			   (this.state == 'Validating') ||
			   (this.state == 'Available') ||
			   (this.state == 'Countdown') ||
			   (this.state == 'InvalidUpdate') || 
			   (this.state == 'InsufficientCharge') ) {
			
			if((this.state == "InvalidUpdate") && (this.autoUpdate === true)){
				return;
			}
			
			if (this.gettingReleaseNotes != true) {
				this.gettingReleaseNotes = true;
				if ("version" in this.payload) {
					this.Depot.setNextVersion(this.payload.version);					
				}			
				
				var sceneArgs = { name: 'detail', transition: Mojo.Transition.crossFade };
				Mojo.Controller.stageController.swapScene(sceneArgs, this.params);
			}
		} else {
		    Mojo.Log.info('Main: Unknown state: ' + this.state);
			this.setSpinner(false);
		}
    },

	setSpinner: function(spin){
		Mojo.Log.info('setSpinner', spin);
		if(spin) {
			this.controller.setMenuVisible(Mojo.Menu.commandMenu, false);
			this.spinner.mojo.start();
		} else {
			if (this.autoUpdate != true) {
				this.controller.setMenuVisible(Mojo.Menu.commandMenu, true);
			}
			this.spinner.mojo.stop();
		}
		
	},
	
	deviceIsUptoDate: function(){
		if (this.systemCheckInProgress == false && this.appCheckInProgress == false) {
			this.setSpinner(false);
			this.controller.get('system-status').innerHTML = $L(label_status_upToDate);
			UpdatesDepot.getDepot().saveDepotObject("releaseDetails", "");
			UpdatesDepot.getDepot().saveDepotObject("newBuildDetails", "");
			this.controller.get('release_notes').style.display = "block";
			this.controller.get('release_notes').style.visibility = "visible";
		} else {
			Mojo.Log.info('device is still checking...');
		}
	},
	
	handleCommand: function(event) {
		if(event.type == Mojo.Event.command) {
			if (event.command == Mojo.Menu.helpCmd) {
				Event.stop(event);
				var openParams = {
					target: 'http://help.palm.com/updates/index.html'
				};
				this.controller.serviceRequest('palm://com.palm.applicationManager', {
					method: 'open',
					parameters: {
						id: 'com.palm.app.help',
						params: openParams
					}
				});
			} else if (event.command == 'checkForUpdates') {
				this.checkButtonCallback();
			}
		} else if (event.type == Mojo.Event.commandEnable && 
		         (event.command == Mojo.Menu.helpCmd)) {
			event.stopPropagation();
		}
	},
	
    activate: function(){
		Mojo.Log.info('Main: activate', this.params.checkForUpdate);
		this.updatesModel.setCallback(this.callback.bind(this));
		
		if (this.systemCheckInProgress == false && this.params.checkForUpdate == true) {
			this.checkForUpdates();
		} else {
			this.controller.get('system-status').innerHTML = $L(label_status_upToDate);
			this.controller.get('release_notes').style.display = "block";
			this.controller.get('release_notes').style.visibility = "visible";
			UpdatesDepot.getDepot().saveDepotObject("releaseDetails", "");
			UpdatesDepot.getDepot().saveDepotObject("newBuildDetails", "");
		}
    },
	
    deactivate: function(){
		Mojo.Log.info('Main: deactivate');
    },
	
    cleanup: function(){
	   
    },

	checkIfAppUpdatesAvailable: function() {
		Mojo.Log.info("------------------- Calling checkIfAppUpdatesAvailable ------------------");
		this.appCheckInProgress = true;

		if (this.serverUrl && this.deviceId && this.carrier && this.token && this.email) {
			this.getUserInstalledApps();
			return true;
		}	

		if(!this.serverUrl)
			AppAssistant.appCatalogService.getServerUrl(this.readServerUrl.bind(this), this.errorServerUrl.bind(this), this.controller );
		if(!this.deviceId)	
			AppAssistant.appCatalogService.getDeviceId(this.readDeviceId.bind(this), this.errorDeviceId.bind(this), this.controller );
		if(!this.carrier)
			AppAssistant.appCatalogService.getCarrier(this.readCarrier.bind(this), this.errorCarrier.bind(this), this.controller );
		if(!this.token || !this.email)
			AppAssistant.appCatalogService.getToken(this.readToken.bind(this), this.errorToken.bind(this), this.controller );
		
	},
	
	readServerUrl: function(response) {
		Mojo.Log.info("readServerUrl response: ", Object.toJSON(response));
		if (response.serverUrl) {
			this.serverUrl = response.serverUrl;
		}
		this.getUserInstalledApps();
	},
	
	errorServerUrl: function (response) {
		Mojo.Log.error("Could not read server url %o", $H(response));
		this.getUserInstalledApps(true);
	},
	
	readDeviceId: function(response) {
		Mojo.Log.info("readDeviceId response: ", Object.toJSON(response));
		if (response.deviceId != undefined) {
			this.deviceId = response.deviceId;
		}
		this.getUserInstalledApps();
	},
	
	errorDeviceId: function (response) {
		Mojo.Log.error("Could not read device id %o", $H(response));
		this.getUserInstalledApps(true);
	},
	
	readCarrier: function (response) {
		Mojo.Log.info("readCarrier response: ", Object.toJSON(response));
		if (Object.values(response) != undefined) {
			this.carrier = Object.values(response).first();
		} else {
			this.carrier = "ROW";
		}
		this.getUserInstalledApps();
	},
	
	errorCarrier: function (response) {
		Mojo.Log.error("Could not read Carrier %o", $H(response));
		this.carrier = "ROW";
		this.getUserInstalledApps();
	},

	readToken: function (response) {
		Mojo.Log.info("readToken response: ", Object.toJSON(response));
		if(response.token) {
			this.token = response.token;
			this.email = response.accountAlias;
		}
		else {
			Mojo.Log.error("Error in reading token");
		}		
		this.getUserInstalledApps();
	},
	
	errorToken: function(response) {
		Mojo.Log.error("Could not read account token %o", $H(response));
		this.getUserInstalledApps(true);
	},
	
	getUserInstalledApps: function(failure) {		
		Mojo.Log.info("getUserInstalledApps");
		if (this.serverUrl && this.deviceId && this.carrier && this.token && this.email) {
			Mojo.Log.info("getUserInstalledApps checking");
			AppAssistant.appCatalogService.getUserInstalledApps(this.serverUrl, this.deviceId, this.carrier, this.token, this.email, 
														this.installedAppResponse.bind(this), this.installedAppError.bind(this));
		}
		
		if(failure == true) {
			this.appCheckInProgress = false;
			this.deviceIsUptoDate();
		}
	},
	
	installedAppResponse: function(response) {
		Mojo.Log.info("Response from server ===================", Object.toJSON(response));
		
		this.appCheckInProgress = false;
		if (response != undefined && response.responseText != "") {
			var jResponse = response.responseText.evalJSON();
			Mojo.Log.info("checkIdAppsAvailable response=", Object.toJSON(jResponse));
			
			if((jResponse.OutAppListForUpdates) && (jResponse.OutAppListForUpdates.appList)) {
				Mojo.Log.info("checkIdAppsAvailable response found");
				
				this.packageUrlArray = jResponse.OutAppListForUpdates.appList;
				
				if (this.systemCheckInProgress == false) {
					this.updateInstalledApps();
				}				
			} else {
				this.deviceIsUptoDate();
			}			
		} else {
			this.deviceIsUptoDate();
		}
		
	},

	installedAppError: function(response) {
		this.appCheckInProgress = false;
		Mojo.Log.error("Error from server ==================== %o", $H(response));
	},
	
	updateInstalledApps: function() {
		if (this.token && this.deviceId) {
			if (this.packageUrlArray) {
				this.controller.get('system-status').innerHTML = $L(label_status_appUpDate);
				this.controller.get('release_notes').style.visibility = "hidden";
				this.controller.get('release_notes').style.display = "none";
				this.setSpinner(false);
				this.controller.get('appButton').style.visibility = "visible";
				return true;
			}
		}
		
		// if app check is not finished then return true because we do not know yet.
		if(this.appCheckInProgress == true){
			return true;
		} else if(this.systemCheckInProgress == false){
			this.deviceIsUptoDate();
		}
		
		return false;
	},
		
 	
});


