/*
 * Copyright (c) 2008 Keith A. Jaska
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 */
package geriatricassistant;

import geriatricassistant.utils.CameraRecorder;
import geriatricassistant.utils.GeriatricAssistantGUI;
import geriatricassistant.utils.WSUtilities;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;

import org.osgi.service.log.LogService;

import com.buglabs.application.IServiceProvider;
import com.buglabs.application.MainApplicationThread;
import com.buglabs.bug.base.pub.ITimeProvider;
import com.buglabs.bug.module.camera.pub.ICameraDevice;
import com.buglabs.bug.module.gps.pub.IPositionProvider;
import com.buglabs.bug.module.lcd.pub.IModuleDisplay;
import com.buglabs.bug.module.motion.pub.IAccelerometerSampleProvider;

/**
 * GeriatricAssistantApplication Main application thread. The run method is
 * invoked by the applications service tracker when all services are accounted
 * for.
 * 
 * @author Keith A. Jaska
 */
public class GeriatricAssistantApplication extends MainApplicationThread {

	private IServiceProvider serviceProv;
	private boolean ran;

	private static Properties props = new Properties();

	/**
	 * Instantiates a new geriatric assistant application.
	 * 
	 * @param serviceProv
	 *            the service provider
	 */
	public GeriatricAssistantApplication(IServiceProvider serviceProv) {
		this.serviceProv = serviceProv;
		try {
			// Loads the properties from the bundled properties file.
			props.load(GeriatricAssistantApplication.class
					.getResourceAsStream("/geriatricassistant.properties"));
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		/**
		 * Let the service tracker know we haven't run yet.
		 */
		ran = false;
	}

	/**
	 * Informs the caller whether this thread ran.
	 */
	public boolean getRan() {
		return ran;
	}

	/**
	 * Let the service tracker know we ran.
	 */
	private void ran() {
		ran = true;
	}

	/**
	 * This method is invoked as a result of all services becoming available for
	 * the application. The list of services is obtained from the getServices()
	 * method.
	 */
	public void run() {
		// Main application loop the run method will commence
		// once all service dependencies are satisfied.
		getLogService().log(LogService.LOG_INFO,
				"Running: GeriatricAssistantApplication");
		CameraRecorder cameraRecorder = new CameraRecorder(getITimeProvider(),
				getICameraDevice(), getLogService());
		cameraRecorder.start();
		GeriatricAssistantGUI gaGUI = new GeriatricAssistantGUI(
				getIModuleDisplay().getFrame(), getITimeProvider(),
				getIPositionProvider(), getLogService());
		while (!tearDownRequested) {

			// * Accelerometer Data Samples
			// * ---------------------------
			// *
			// * The accelerometer analog outputs are sampled with a 10 bit A/D
			// * converter using 2.9V as a reference.
			// *
			// * An accelerometer output of 1.45V corresponds to "0g".
			// *
			// * The accelerometer outputs are scaled by the sensitivity
			// * settings.
			// *
			// * sensitivity scale factor
			// * ---------------------------
			// * 0 = 2.5G, 421 mV/G
			// * 1 = 3.3G, 316 mV/G
			// * 2 = 6.7G, 158 mV/G
			// * 3 = 10G, 105 mV/G
			// *
			// * The following equation converts an A/D sample to a G-Force
			// * value.
			// *
			// * G-force = ( ((digital sample) * (X mV/bit)) - 1450 mV) / (scale
			// * factor )

			/*
			 * TODO: Uncomment the following to enable "free fall" detection I believe
			 * this is currently unsupported by the VirtualBUG.
			 */
			// short[] sample = getIAccelerometerSampleProvider().readSample();
			// double gForceX = (((sample[0]) * (105.25)) - 1450) / (421);
			// double gForceY = (((sample[1]) * (105.25)) - 1450) / (421);
			// double gForceZ = (((sample[2]) * (105.25)) - 1450) / (421);
			// double gForceComb = gForceX + gForceY + gForceZ;
			// if (gForceComb > (-0.5) && gForceComb < (0.5)) {
			// // FREE FALL DETECTED
			// LatLon position = getIPositionProvider().getLatitudeLongitude();
			// String imageUrl = WSUtilities.YahooMaps(position.latitude,
			// position.longitude);
			// WSUtilities.postImageToTumblr(imageUrl, position.latitude,
			// position.longitude, getITimeProvider().getTime());
			// }
		}
		getLogService().log(LogService.LOG_INFO,
				"GeriatricAssistantApplication stopped");

		/**
		 * Let the service tracker know we ran.
		 */
		ran();
	}

	/**
	 * Provides a list of service names that this application depends on.
	 * 
	 */
	public List getServices() {
		List services = new ArrayList();
		services.add("com.buglabs.bug.base.pub.ITimeProvider");
		services.add("com.buglabs.bug.module.camera.pub.ICameraDevice");
		services.add("com.buglabs.bug.module.gps.pub.IPositionProvider");
		services.add("com.buglabs.bug.module.lcd.pub.IModuleDisplay");
		// services.add("com.buglabs.bug.module.motion.pub.IAccelerometerSampleProvider");
		services.add("org.osgi.service.log.LogService");
		return services;
	}

	/**
	 * Queries the service provider for IAccelerometerSampleProvider
	 * 
	 * @return a handle to the a(n) IAccelerometerSampleProvider service.
	 */
	private IAccelerometerSampleProvider getIAccelerometerSampleProvider() {
		return (IAccelerometerSampleProvider) serviceProv
				.getService(IAccelerometerSampleProvider.class);
	}

	/**
	 * Queries the service provider for ITimeProvider.
	 * 
	 * @return a handle to the a(n) ITimeProvider service.
	 */
	private ITimeProvider getITimeProvider() {
		return (ITimeProvider) serviceProv.getService(ITimeProvider.class);
	}

	/**
	 * Queries the service provider for ICameraDevice.
	 * 
	 * @return a handle to the a(n) ICameraDevice service.
	 */
	private ICameraDevice getICameraDevice() {
		return (ICameraDevice) serviceProv.getService(ICameraDevice.class);
	}

	/**
	 * Queries the service provider for IPositionProvider.
	 * 
	 * @return a handle to the a(n) IPositionProvider service.
	 */
	private IPositionProvider getIPositionProvider() {
		return (IPositionProvider) serviceProv
				.getService(IPositionProvider.class);
	}

	/**
	 * Queries the service provider for IModuleDisplay.
	 * 
	 * @return a handle to the a(n) IModuleDisplay service.
	 */
	private IModuleDisplay getIModuleDisplay() {
		return (IModuleDisplay) serviceProv.getService(IModuleDisplay.class);
	}

	/**
	 * Queries the service provider for LogService.
	 * 
	 * @return a handle to the a(n) LogService service.
	 */
	private LogService getLogService() {
		return (LogService) serviceProv.getService(LogService.class);
	}

	/**
	 * Gets a property from geriatricassistant.properties based on the key.
	 * Additionally, you can pass in a default value (in the case where the
	 * property is not set).
	 * 
	 * @param key
	 *            the key
	 * @param defaultValue
	 *            the default value
	 * 
	 * @return the property
	 */
	public static String getProperty(String key, String defaultValue) {
		String property = props.getProperty(key, defaultValue);
		if (property == null || "".equals(property)) {
			System.err
					.println(key
							+ " is not set!  You must set this in the properties file in order to use this feature.");
			System.exit(0);
		}
		return property;
	}

}