package de.tudarmstadt.informatik.hostage.logging;

import java.util.ArrayList;

import android.app.IntentService;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.os.ResultReceiver;

/**
 * An {@link IntentService} subclass for handling asynchronous task requests in
 * a service on a separate handler thread.
 * 
 * @author Mihai Plasoianu
 */
public class Logger extends IntentService {

	private static final String ACTION_LOG = "de.tudarmstadt.informatik.hostage.action.LOG";
	private static final String ACTION_GET_RECORD_ALL = "de.tudarmstadt.informatik.hostage.action.GET_RECORD_ALL";
	private static final String ACTION_GET_RECORD_EACH = "de.tudarmstadt.informatik.hostage.action.GET_RECORD_EACH";
	private static final String ACTION_GET_RECORD_ID = "de.tudarmstadt.informatik.hostage.action.GET_RECORD_ID";
	private static final String ACTION_GET_COUNT_ALL = "de.tudarmstadt.informatik.hostage.action.GET_COUNT_ALL";
	private static final String ACTION_GET_COUNT_PROTOCOL = "de.tudarmstadt.informatik.hostage.action.GET_COUNT_PROTOCOL";
	private static final String ACTION_GET_ATTACK_MIN = "de.tudarmstadt.informatik.hostage.action.GET_ATTACK_MIN";
	private static final String ACTION_GET_ATTACK_MAX = "de.tudarmstadt.informatik.hostage.action.GET_ATTACK_MAX";
	private static final String ACTION_IS_BSSID_SEEN = "de.tudarmstadt.informatik.hostage.action.IS_BSSID_SEEN";
	private static final String ACTION_GET_BSSID_ALL = "de.tudarmstadt.informatik.hostage.action.GET_BSSID_ALL";
	private static final String ACTION_GET_SSID_BSSID = "de.tudarmstadt.informatik.hostage.action.GET_SSID_BSSID";
	private static final String ACTION_CLEAR_DATE = "de.tudarmstadt.informatik.hostage.action.CLEAR_DATE";
	private static final String ACTION_CLEAR_BSSID = "de.tudarmstadt.informatik.hostage.action.CLEAR_BSSID";
	private static final String ACTION_CLEAR_ALL = "de.tudarmstadt.informatik.hostage.action.CLEAR_ALL";

	private static final String EXTRA_RECORD = "de.tudarmstadt.informatik.hostage.extra.RECORD";
	private static final String EXTRA_PROTOCOL = "de.tudarmstadt.informatik.hostage.extra.PROTOCOL";
	private static final String EXTRA_BSSID = "de.tudarmstadt.informatik.hostage.extra.BSSID";
	private static final String EXTRA_PRIMITIVE = "de.tudarmstadt.informatik.hostage.extra.PRIMITIVE";

	private static final String RESULT_RECEIVER = "de.tudarmstadt.informatik.hostage.RESULT_RECEIVER";

	public static void deleteAll(Context context) {
		Intent intent = new Intent(context, Logger.class);
		intent.setAction(ACTION_CLEAR_ALL);
		context.startService(intent);
	}

	public static void deleteByBssid(Context context, String bssid) {
		Intent intent = new Intent(context, Logger.class);
		intent.setAction(ACTION_CLEAR_BSSID);
		intent.putExtra(EXTRA_BSSID, bssid);
		context.startService(intent);
	}

	public static void deleteByDate(Context context, long time) {
		Intent intent = new Intent(context, Logger.class);
		intent.setAction(ACTION_CLEAR_DATE);
		intent.putExtra(EXTRA_PRIMITIVE, time);
		context.startService(intent);
	}

	public static void getAllBssids(Context context, ResultReceiver receiver) {
		Intent intent = new Intent(context, Logger.class);
		intent.setAction(ACTION_GET_BSSID_ALL);
		intent.putExtra(RESULT_RECEIVER, receiver);
		context.startService(intent);
	}

	public static void getAllRecords(Context context, ResultReceiver receiver) {
		Intent intent = new Intent(context, Logger.class);
		intent.setAction(ACTION_GET_RECORD_ALL);
		intent.putExtra(RESULT_RECEIVER, receiver);
		context.startService(intent);
	}

	public static void getAttackCount(Context context, ResultReceiver receiver) {
		Intent intent = new Intent(context, Logger.class);
		intent.setAction(ACTION_GET_COUNT_ALL);
		intent.putExtra(RESULT_RECEIVER, receiver);
		context.startService(intent);
	}

	public static void getAttackPerProtocolCount(Context context,
			String protocol, ResultReceiver receiver) {
		Intent intent = new Intent(context, Logger.class);
		intent.setAction(ACTION_GET_COUNT_PROTOCOL);
		intent.putExtra(EXTRA_PROTOCOL, protocol);
		intent.putExtra(RESULT_RECEIVER, receiver);
		context.startService(intent);
	}

	public static void getMaxAttackId(Context context, ResultReceiver receiver) {
		Intent intent = new Intent(context, Logger.class);
		intent.setAction(ACTION_GET_ATTACK_MAX);
		intent.putExtra(RESULT_RECEIVER, receiver);
		context.startService(intent);
	}

	public static void getMinAttackId(Context context, ResultReceiver receiver) {
		Intent intent = new Intent(context, Logger.class);
		intent.setAction(ACTION_GET_ATTACK_MIN);
		intent.putExtra(RESULT_RECEIVER, receiver);
		context.startService(intent);
	}

	public static void getRecordOfAttackId(Context context, long attack_id,
			ResultReceiver receiver) {
		Intent intent = new Intent(context, Logger.class);
		intent.setAction(ACTION_GET_RECORD_ID);
		intent.putExtra(EXTRA_PRIMITIVE, attack_id);
		intent.putExtra(RESULT_RECEIVER, receiver);
		context.startService(intent);
	}

	public static void getRecordOfEachAttack(Context context,
			int lastUploadedAttackId, ResultReceiver receiver) {
		Intent intent = new Intent(context, Logger.class);
		intent.setAction(ACTION_GET_RECORD_EACH);
		intent.putExtra(EXTRA_PRIMITIVE, lastUploadedAttackId);
		intent.putExtra(RESULT_RECEIVER, receiver);
		context.startService(intent);
	}

	public static void getSsid(Context context, String bssid,
			ResultReceiver receiver) {
		Intent intent = new Intent(context, Logger.class);
		intent.setAction(ACTION_GET_SSID_BSSID);
		intent.putExtra(EXTRA_BSSID, bssid);
		intent.putExtra(RESULT_RECEIVER, receiver);
		context.startService(intent);
	}

	public static void isBssidSeen(Context context, String protocol,
			String bssid, ResultReceiver receiver) {
		Intent intent = new Intent(context, Logger.class);
		intent.setAction(ACTION_IS_BSSID_SEEN);
		intent.putExtra(EXTRA_PROTOCOL, protocol);
		intent.putExtra(EXTRA_BSSID, bssid);
		intent.putExtra(RESULT_RECEIVER, receiver);
		context.startService(intent);
	}

	public static void log(Context context, Record record) {
		Intent intent = new Intent(context, Logger.class);
		intent.setAction(ACTION_LOG);
		intent.putExtra(EXTRA_RECORD, record);
		context.startService(intent);
	}

	private UglyDbHelper mDbHelper;

	public Logger() {
		super("Logger");
	}

	@Override
	public void onCreate() {
		super.onCreate();
		mDbHelper = new UglyDbHelper(getApplicationContext());
	}

	private boolean handleActionBssidSeen(String protocol, String bssid) {
		return mDbHelper.bssidSeen(protocol, bssid);
	}

	/**
	 * Delete all records.
	 */
	private void handleActionDeleteAll() {
		mDbHelper.clearData();
	}

	private void handleActionDeleteByBssid(String bssid) {
		mDbHelper.deleteByBSSID(bssid);
	}

	private void handleActionDeleteByDate(long time) {
		mDbHelper.deleteByDate(time);
	}

	private String[] handleActionGetAllBssids() {
		return mDbHelper.getAllBSSIDS();
	}

	private ArrayList<Record> handleActionGetAllRecords() {
		return mDbHelper.getAllRecords();
	}

	private int handleActionGetAttackCount() {
		return mDbHelper.getAttackCount();
	}

	private int handleActionGetAttackPerProtocolCount(String protocol) {
		return mDbHelper.getAttackPerProtocolCount(protocol);
	}

	private long handleActionGetMaxAttackId() {
		return mDbHelper.getHighestAttackId();
	}

	private long handleActionGetMinAttackId() {
		return mDbHelper.getSmallestAttackId();
	}

	private Record handleActionGetRecordOfAttackId(long attack_id) {
		return mDbHelper.getRecordOfAttackId(attack_id);
	}

	private ArrayList<Record> handleActionGetRecordOfEachAttack(
			int lastUploadedAttackId) {
		return mDbHelper.getRecordOfEachAttack(lastUploadedAttackId);
	}

	private String handleActionGetSsid(String bssid) {
		return mDbHelper.getSSID(bssid);
	}

	/**
	 * Log a record.
	 */
	private void handleActionLog(Record record) {
		mDbHelper.addRecord(record);
	}

	@Override
	protected void onHandleIntent(Intent intent) {
		if (intent != null) {
			final String action = intent.getAction();
			if (ACTION_LOG.equals(action)) {
				final Record record = intent.getParcelableExtra(EXTRA_RECORD);
				handleActionLog(record);
			} else if (ACTION_GET_RECORD_ALL.equals(action)) {
				ResultReceiver receiver = intent
						.getParcelableExtra(RESULT_RECEIVER);
				ArrayList<Record> r = handleActionGetAllRecords();
				Bundle result = new Bundle();
				result.putParcelableArrayList("result", r);
				receiver.send(0, result);
			} else if (ACTION_GET_RECORD_EACH.equals(action)) {
				final int lastUploadedAttackId = intent.getIntExtra(
						EXTRA_PRIMITIVE, -1);
				ResultReceiver receiver = intent
						.getParcelableExtra(RESULT_RECEIVER);
				ArrayList<Record> r = handleActionGetRecordOfEachAttack(lastUploadedAttackId);
				Bundle result = new Bundle();
				result.putParcelableArrayList("result", r);
				receiver.send(0, result);
			} else if (ACTION_GET_RECORD_ID.equals(action)) {
				final int attack_id = intent.getIntExtra(EXTRA_PRIMITIVE, -1);
				ResultReceiver receiver = intent
						.getParcelableExtra(RESULT_RECEIVER);
				Record r = handleActionGetRecordOfAttackId(attack_id);
				Bundle result = new Bundle();
				result.putParcelable("result", r);
				receiver.send(0, result);
			} else if (ACTION_GET_COUNT_ALL.equals(action)) {
				ResultReceiver receiver = intent
						.getParcelableExtra(RESULT_RECEIVER);
				int r = handleActionGetAttackCount();
				Bundle result = new Bundle();
				result.putInt("result", r);
				receiver.send(0, result);
			} else if (ACTION_GET_COUNT_PROTOCOL.equals(action)) {
				final String protocol = intent.getStringExtra(EXTRA_PROTOCOL);
				ResultReceiver receiver = intent
						.getParcelableExtra(RESULT_RECEIVER);
				int r = handleActionGetAttackPerProtocolCount(protocol);
				Bundle result = new Bundle();
				result.putInt("result", r);
				receiver.send(0, result);
			} else if (ACTION_GET_ATTACK_MIN.equals(action)) {
				ResultReceiver receiver = intent
						.getParcelableExtra(RESULT_RECEIVER);
				long r = handleActionGetMinAttackId();
				Bundle result = new Bundle();
				result.putLong("result", r);
				receiver.send(0, result);
				handleActionGetMinAttackId();
			} else if (ACTION_GET_ATTACK_MAX.equals(action)) {
				ResultReceiver receiver = intent
						.getParcelableExtra(RESULT_RECEIVER);
				long r = handleActionGetMaxAttackId();
				Bundle result = new Bundle();
				result.putLong("result", r);
				receiver.send(0, result);
			} else if (ACTION_IS_BSSID_SEEN.equals(action)) {
				final String protocol = intent.getStringExtra(EXTRA_PROTOCOL);
				final String bssid = intent.getStringExtra(EXTRA_BSSID);
				ResultReceiver receiver = intent
						.getParcelableExtra(RESULT_RECEIVER);
				boolean r = handleActionBssidSeen(protocol, bssid);
				Bundle result = new Bundle();
				result.putBoolean("result", r);
				receiver.send(0, result);
			} else if (ACTION_GET_BSSID_ALL.equals(action)) {
				ResultReceiver receiver = intent
						.getParcelableExtra(RESULT_RECEIVER);
				String[] r = handleActionGetAllBssids();
				Bundle result = new Bundle();
				result.putStringArray("result", r);
				receiver.send(0, result);
			} else if (ACTION_GET_SSID_BSSID.equals(action)) {
				final String bssid = intent.getStringExtra(EXTRA_BSSID);
				ResultReceiver receiver = intent
						.getParcelableExtra(RESULT_RECEIVER);
				String r = handleActionGetSsid(bssid);
				Bundle result = new Bundle();
				result.putString("result", r);
				receiver.send(0, result);
			} else if (ACTION_CLEAR_DATE.equals(action)) {
				final long time = intent.getLongExtra(EXTRA_PRIMITIVE, -1L);
				handleActionDeleteByDate(time);
			} else if (ACTION_CLEAR_BSSID.equals(action)) {
				final String bssid = intent.getStringExtra(EXTRA_BSSID);
				handleActionDeleteByBssid(bssid);
			} else if (ACTION_CLEAR_ALL.equals(action)) {
				handleActionDeleteAll();
			}
		}
	}

}
