/**
 * Generated by DragonFly.
 *
 */
package xmastree2;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Random;

import com.buglabs.bug.base.pub.IBUGBaseControl;
import com.buglabs.bug.module.vonhippel.pub.IVonHippelModuleControl;
import com.buglabs.device.ButtonEvent;
import com.buglabs.device.IBaseDisplay;
import com.buglabs.device.IButtonEventListener;
import com.buglabs.device.IButtonEventProvider;
import com.buglabs.module.IModuleLEDController;
import com.buglabs.util.LogServiceUtil;
import com.buglabs.util.ServiceFilterGenerator;
import org.osgi.framework.BundleActivator;
import org.osgi.framework.BundleContext;
import org.osgi.framework.Filter;
import org.osgi.framework.ServiceReference;
import org.osgi.service.log.LogService;
import org.osgi.util.tracker.ServiceTracker;
import org.osgi.util.tracker.ServiceTrackerCustomizer;

/**
 * BundleActivator for XmasTree2.
 * 
 */
public class Activator implements BundleActivator, ServiceTrackerCustomizer,
		IButtonEventListener {
	private ServiceTracker st;
	private IBUGBaseControl bbc;
	private List mlc;
	private List vhlc;
	private int blinkRate = 1000;
	private BundleContext context;
	private ApplicationThread app;
	private LogService log;

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.osgi.framework.BundleActivator#start(org.osgi.framework.BundleContext)
	 */
	public void start(BundleContext context) throws Exception {
		this.context = context;
		mlc = new ArrayList();
		vhlc = new ArrayList();

		// Get a reference to the log service.
		log = LogServiceUtil.getLogService(context);

		// Here we define which services are available that can make light.
		List slist = new ArrayList();
		slist.add(IBUGBaseControl.class.getName());
		slist.add(IModuleLEDController.class.getName());
		slist.add(IVonHippelModuleControl.class.getName());
		slist.add(IButtonEventProvider.class.getName());

		// Generate the OSGi LDAP-style filter expression
		Filter f = context.createFilter(ServiceFilterGenerator
				.generateServiceFilter(slist));
		st = new ServiceTracker(context, f, this);
		st.open();

		app = new ApplicationThread();
		app.start();
		log.log(LogService.LOG_INFO, "xmastree2 started.");
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.osgi.framework.BundleActivator#stop(org.osgi.framework.BundleContext)
	 */
	public void stop(BundleContext context) throws Exception {
		log.log(LogService.LOG_INFO, "xmastree2 stopping");
		app.interrupt();

		if (bbc != null) {
			for (int i = 0; i < 4; ++i) {
				bbc.clearLED(i);
			}
		}

		for (Iterator i = mlc.iterator(); i.hasNext();) {
			IModuleLEDController mc = (IModuleLEDController) i.next();
			mc.setLEDGreen(false);
			mc.setLEDRed(false);
		}

		st.close();
	}

	public Object addingService(ServiceReference reference) {
		Object service = context.getService(reference);

		if (service instanceof IBUGBaseControl) {
			bbc = (IBUGBaseControl) service;
			return service;
		}

		if (service instanceof IModuleLEDController) {
			if (!mlc.contains(service)) {
				mlc.add(service);
			}
		}

		if (service instanceof IVonHippelModuleControl) {
			if (!vhlc.contains(service)) {
				vhlc.add(service);
			}
		}

		if (service instanceof IButtonEventProvider) {
			((IButtonEventProvider) service).addListener(this);
		}

		return service;
	}

	public void modifiedService(ServiceReference reference, Object service) {

	}

	public void removedService(ServiceReference reference, Object service) {
		if (service instanceof IBUGBaseControl) {
			bbc = null;
		} else if (service instanceof IModuleLEDController) {
			synchronized (mlc) {
				mlc.remove(service);
			}
		} else if (service instanceof IVonHippelModuleControl) {
			synchronized (vhlc) {
				vhlc.remove(service);
			}
		} else if (service instanceof IButtonEventProvider) {
			((IButtonEventProvider) service).removeListener(this);
		}
	}

	private class ApplicationThread extends Thread {
		public void run() {
			Random rng = new Random();

			try {
				while (true) {
					try {
						// Handle base LEDs
						if (bbc != null) {
							for (int i = 0; i < 4; ++i) {
								bbc.clearLED(i);
							}
							bbc.setLED(rng.nextInt(4));
						}

						// Iterate through all Module LEDs
						synchronized (mlc) {
							for (Iterator i = mlc.iterator(); i.hasNext();) {
								IModuleLEDController mc = (IModuleLEDController) i
										.next();
								mc.setLEDGreen(rng.nextBoolean());
								mc.setLEDRed(rng.nextBoolean());
							}
						}

						// Now try the VH LEDs
						synchronized (vhlc) {
							for (Iterator i = vhlc.iterator(); i.hasNext();) {
								IVonHippelModuleControl mc = (IVonHippelModuleControl) i
										.next();
								for (int j = 0; j < 4; ++j) {
									mc.makeIOXOut(j);
									if (rng.nextBoolean()) {
										mc.clearIOX(j);
									} else {
										mc.setIOX(j);
									}
								}
							}
						}

						Thread.sleep(blinkRate);
					} catch (IOException e) {
						// We want to ignore IO exceptions because this can
						// happen when a module is removed
					}
				}
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}

			log.log(LogService.LOG_INFO, "xmastree2 app thread stopped.");
		}
	}

	public void buttonEvent(ButtonEvent event) {

		if (event.getButton() == ButtonEvent.BUTTON_HOTKEY_1) {
			blinkRate = blinkRate - 50;
			if (blinkRate < 0) {
				blinkRate = 10;
			}
		} else if (event.getButton() == ButtonEvent.BUTTON_HOTKEY_4) {
			blinkRate += 50;
		}
	}
}