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

LocationWatcherInterval = 60 * 60 * 1000; //Check location every hour
LocationWatcherFreshTime = 1000 * 60 * 60 * 24; //If we don't have a location watched in more than this time, something is wrong, we've stopped watching locations probably
ignoreDistancesForTravel = false;
MinimumDistanceForTravel = 75;
LocationSchedulerKey = "LocationWatcherForAirplaneNotifications";

calculateCoordinateDistance = function(lat1, lon1, lat2, lon2){
	var lat1r = Math.PI * lat1/180;
	var lat2r = Math.PI * lat2/180;
	var theta = Math.PI * (lon1-lon2) /180;
	var dist = Math.sin(lat1r) * Math.sin(lat2r) + Math.cos(lat1r) * Math.cos(lat2r) * Math.cos(theta);
	dist = Math.acos(dist);
	dist = dist * 180/Math.PI;
	dist = dist * 60 * 1.1515;
	return dist;             
};

var NotificationAssistant = Class.create({
    initialize: function(controller){
        this.controller = controller;
        
        this.currentAirplaneState = null;
        this.lastUpdateTime = 0;
        
        this.subscribeToNotifications();
        this.lastLocation = {};
        this.startLocationWatcher();

    },
	
	//Cancel all old tasks, create a new one, and run it immediately.
	taskResponse:function(resubscribe, resp){
		this.requests = [];
		for(var i = 0; i < resp.tasks.length; i++){
			new Mojo.Service.Request("palm://com.palm.taskScheduler", {
				method:"removeTask",
				parameters:{
					"taskId":resp.tasks[i].taskId
				}
			});
		}
		if (resubscribe) {
			var appParams = {
				launchType: "fetchLocation"
			};
			
			this.taskRequest = new Mojo.Service.Request("palm://com.palm.taskScheduler", {
				method: "scheduleTask",
				parameters: {
					uri: "palm://com.palm.applicationManager/open",
					arguments: {
						id: "com.palm.app.contacts",
						params: appParams
					},
					repeatInterval: LocationWatcherInterval,
					key: LocationSchedulerKey,
					misfirePolicy: {
						executeNow: true
					}
				}
			});
		}
	},
	
	
    
    log: function(str){
        //console.log(str)
    },
    
    runLocationWatcher: function(){
        this.autoLocateRequest = new Mojo.Service.Request("palm://com.palm.location", {
            method: 'getAutoLocate',
            parameters: {},
            onSuccess: this.autoLocateResponse.bind(this)
        });
        
    },
    
    autoLocateResponse: function(resp){
		this.autoLocateRequest = null;
        if (resp.autoLocate) {
            this.watchLocationRequest = new Mojo.Service.Request("palm://com.palm.location", {
                method: 'getCurrentPosition',
                parameters: {
                    accuracy: 3,
                    appId: 'com.palm.app.contacts'
                },
                onSuccess: this.handleLocationWatching.bind(this),
                onFailure: this.handleLocationWatching.bind(this)
            });
        }
    },
	
	startLocationWatcher:function(){
		this._getTasks(true);	
	},
    
    stopLocationWatcher: function(){
		this._getTasks(false);
    },
	
	_getTasks:function(resubscribe){
		this.taskRequest = new Mojo.Service.Request("palm://com.palm.taskScheduler", {
			method:"getTasks",
			parameters: {
				"key":LocationSchedulerKey
			},
			onSuccess:this.taskResponse.bind(this, resubscribe)
		});
	},
    
    handleLocationWatching: function(resp){
		this.watchLocationRequest = null;
        console.log("LocationWatcher resp: " + Object.toJSON(resp));
        if (!resp.latitude) {
            return;
		}
		this.lastLocationWatchTime = new Date().getTime();
        this.lastLocation.lat = resp.latitude;
        this.lastLocation.lon = resp.longitude;
    },
    
    subscribeToNotifications: function(){
        AppAssistant.airplaneService.registerForEvents(this.updateAirplaneState.bind(this));
    },
    
    updateAirplaneState: function(response){
		console.log("Airplane state is " + Object.toJSON(response));
        //if(!Mojo.Controller.getAppController().prefsModel.airplane) return;
        var oldState = this.currentAirplaneState;
        this.currentAirplaneState = response.airplaneMode;
        var time = new Date().getTime();
        var elapsed = time - this.lastUpdateTime;
        this.lastUpdateTime = time;
        if (oldState === null) {
            return;
        }
        
        if (oldState == this.currentAirplaneState) {
            return;
        }
        
        if (this.currentAirplaneState) {
            this.stopLocationWatcher();
        } else {
	      this.currentLocationRequest = new Mojo.Service.Request("palm://com.palm.location", {
	            method: 'getAutoLocate',
	            parameters: {},
	            onSuccess: this.requestCMStatus.bind(this)
	        });
        }
        
    },
	
	requestCMStatus:function(resp){
		if (resp.autoLocate) {
			//console.log("Requesting data")
			this.connectionRequest = new Mojo.Service.Request('palm://com.palm.connectionmanager', {
				method: 'getstatus',
				parameters: {
					"subscribe": true
				},
				onSuccess: this.handleCmStatus.bind(this, {})
			});
		} else {
			//If autolocate is off, start the location watcher here, so that if it ever does get turned on this will still work.
			this.startLocationWatcher();
		}	
	},
	
	
     handleCmStatus: function(params, resp){
	 	//console.log("Data response : " + Object.toJSON(resp))
        if (resp.isInternetConnectionAvailable) {
            this.connectionRequest.cancel();
            this.findGeoLocation(params);
        }
    },
       
    findGeoLocation: function(params){
		
        this.log("Lets find the location with params : " + Object.toJSON(params));
        this.currentLocationRequest = new Mojo.Service.Request("palm://com.palm.location", {
            method: 'getCurrentPosition',
            parameters: {
                accuracy: 3,
				maximumAge:0,
                appId: 'com.palm.app.contacts'
            },
            onSuccess: this.handleLocationResponse.bind(this, params),
            onFailure: this.handleLocationResponse.bind(this, params)
        });
		this.startLocationWatcher();
    },
    
    handleLocationResponse: function(params, resp){
        if (!resp.latitude) {
            return;
		}
        this.currentLocationRequest.cancel();
        this.currentLocationRequest = null;
        
        params.lat = resp.latitude;
        params.lon = resp.longitude;
        fetchWeatherData(this.handleWeatherData.bind(this, params), params);
        return;
    },
    
    handleWeatherData: function(params, weatherData){
		console.log("Handling weather data\n\n\n");
		var currentTimestamp = new Date().getTime();
		console.log("1");
		var timeSinceLastWatch = currentTimestamp - this.lastLocationWatchTime;
		console.log("Last time was " + this.lastLocationWatchTime + " and time since is " + timeSinceLastWatch);

		if(!this.lastLocationWatchTime || (timeSinceLastWatch > LocationWatcherFreshTime)){
			console.log("The time since the last watch time is " + timeSinceLastWatch + " We must have stopped watching locations.");
			
			Mojo.Log.warn("The time since the last watch time is " + timeSinceLastWatch + " We must have stopped watching locations.");
			return;
		}
		console.log("Calclating distances between \n"+ params.lat + "\n" + params.lon + "\n" + this.lastLocation.lat + "\n" + this.lastLocation.lon);
        var distance = calculateCoordinateDistance(params.lat, params.lon, this.lastLocation.lat, this.lastLocation.lon);
        console.log("Distance is : " + distance + " and last location is " + Object.toJSON(this.lastLocation));
        //XXX If distance is less than 50 we should just return here and do nothing.  We didn't go anywhere.
        if (distance < 50 && !ignoreDistancesForTravel) {
            return;
		}
        Object.extend(params, weatherData);
        
        var bannerText = "Welcome To " + params.city + ", " + params.state;
        var bannerParams = {
            messageText: bannerText,
            icon: "images/locationwatcher/flight-mode-icon-small.png"
        };
        this.controller.showBanner(bannerText, {
            action: 'showDashboard'
        }, '');
        
        params.weather = weatherData.description + " - Hi: " + weatherData.high + " Lo: " + weatherData.low;
        params.icon = weatherData.icon;
        this.launchAirplaneNotification(params);
    },
    
    launchAirplaneNotification: function(params){
        // Create a dashboard
        var f = function(stageController){
            stageController.pushScene('airplaneArrival', params);
        }.bind(this);
        var stageparams = {
            name: "AirplaneWeatherStage",
            lightweight: true
        };
        
        this.controller.createStageWithCallback(stageparams, f, 'dashboard');
    }
});
