/**
 * Appcelerator Titanium Mobile
 * Copyright (c) 2009-2010 by Appcelerator, Inc. All Rights Reserved.
 * Licensed under the terms of the Apache Public License
 * Please see the LICENSE included with this distribution for details.
 */
package ti.modules.titanium;

import java.io.IOException;
import java.io.InputStream;
import java.util.Date;
import java.util.HashMap;
import java.util.Properties;
import java.util.Timer;
import java.util.TimerTask;

import org.appcelerator.titanium.TiContext;
import org.appcelerator.titanium.TiDict;
import org.appcelerator.titanium.TiModule;
import org.appcelerator.titanium.kroll.KrollCallback;
import org.appcelerator.titanium.util.Log;
import org.appcelerator.titanium.util.TiConvert;
import org.appcelerator.titanium.util.TiUIHelper;

public class TitaniumModule
	extends TiModule
{
	private static final String LCAT = "TitaniumModule";
	private static TiDict constants;
	private static String buildVersion;
	private static String buildTimestamp;

	static {
		buildVersion = "1.0";
		buildTimestamp = "N/A";
		InputStream versionStream = TitaniumModule.class.getClassLoader().getResourceAsStream("org/appcelerator/titanium/build.properties");
		if (versionStream != null) {
			Properties properties = new Properties();
			try {
				properties.load(versionStream);
				if (properties.containsKey("build.version")) {
					buildVersion = properties.getProperty("build.version");
				}
				if (properties.containsKey("build.timestamp")) {
					buildTimestamp = properties.getProperty("build.timestamp");
				}
			} catch (IOException e) {}
		}
	}

	public TitaniumModule(TiContext tiContext) {
		super(tiContext);

	}

	@Override
	public TiDict getConstants()
	{
		if (constants == null) {
			constants = new TiDict();

			constants.put("version", buildVersion);
			constants.put("buildTimestamp", buildTimestamp);
		}

		return constants;
	}

	public void include(Object[] files) {
		for(Object filename : files) {
			try {
				getTiContext().evalFile(getTiContext().resolveUrl(null, TiConvert.toString(filename)));
			} catch (IOException e) {
				Log.e(LCAT, "Error while evaluating: " + filename, e);
			}
		}
	}

	private HashMap<Integer, Timer> timers = new HashMap<Integer, Timer>();
	private int currentTimerId;

	private int createTimer(Object fn, long timeout, final Object[] args, final boolean interval)
		throws IllegalArgumentException
	{
		// TODO: we should handle evaluatable code eventually too..
		if (fn instanceof KrollCallback) {
			final KrollCallback callback = (KrollCallback) fn;
			Timer timer = new Timer();
			final int timerId = currentTimerId++;

			timers.put(timerId, timer);
			TimerTask task = new TimerTask() {
				@Override
				public void run() {
					Log.d(LCAT, "calling " + (interval?"interval":"timeout") + " timer " + timerId + " @" + new Date().getTime());
					callback.call(args);
				}
			};

			if (interval) {
				timer.schedule(task, timeout, timeout);
			} else {
				timer.schedule(task, timeout);
			}

			return timerId;
		}
		else throw new IllegalArgumentException("Don't know how to call callback of type: " + fn.getClass().getName());
	}

	public int setTimeout(Object fn, long timeout, final Object[] args)
		throws IllegalArgumentException
	{
		return createTimer(fn, timeout, args, false);
	}

	public void clearTimeout(int timerId) {
		if (timers.containsKey(timerId)) {
			Timer timer = timers.remove(timerId);
			timer.cancel();
		}
	}

	public int setInterval(Object fn, long timeout, final Object[] args)
		throws IllegalArgumentException
	{
		return createTimer(fn, timeout, args, true);
	}

	public void clearInterval(int timerId) {
		clearTimeout(timerId);
	}

	public void alert(Object message) {
		String msg = (message == null? null : message.toString());
		Log.i("ALERT", msg);
		TiUIHelper.doOkDialog(getTiContext().getActivity(), "Alert", msg, null);
	}
}

@@ -630,16 +630,69 @@
 llback;%0A
+import org.appcelerator.titanium.kroll.KrollContext;%0A
 import o
@@ -826,16 +826,51 @@
 elper;%0A%0A
+import sun.awt.geom.AreaOp.AddOp;%0A%0A
 public c
@@ -1736,16 +1736,62 @@
 ntext);%0A
+%09%09tiContext.addOnLifecycleEventListener(this);
 %0A%09%7D%0A%0A%09@O
@@ -3997,10 +3997,315 @@
 ll);%0A%09%7D%0A
+%09%0A%09@Override%0A%09public void onDestroy() %7B%0A%09%09cancelTimers();%0A%09%09super.onDestroy();%0A%09%7D%0A%09%0A%09@Override%0A%09public void onStop() %7B%0A%09%09cancelTimers();%0A%09%09super.onStop();%0A%09%7D%0A%09%0A%09public void cancelTimers() %7B%0A%09%09for (Timer timer: timers.values()) %7B%0A%09%09%09if (timer != null) %7B%0A%09%09%09%09timer.cancel();%0A%09%09%09%7D%0A%09%09%7D%0A%09%09timers.clear();%0A%09%7D%0A%09%0A
 %7D%0A

clear timers on destroy/stop of context [#866 state:resolved]