package guard.api.sensitive.ui.sapiguard.hookedapis;

import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.Intent;
import android.graphics.Bitmap;
import android.nfc.NfcAdapter;
import android.os.Environment;
import android.provider.Telephony;
import android.service.notification.NotificationListenerService;
import android.telephony.TelephonyManager;
import android.util.Log;
import android.view.View;

import java.io.File;
import java.io.FileOutputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import guard.api.sensitive.ui.sapiguard.XHook;
import guard.api.sensitive.ui.sapiguard.utils.PrivacyManager;
import guard.api.sensitive.ui.sapiguard.utils.XParam;

@SuppressLint("InlinedApi")
public class XActivityThread extends XHook {
	private Methods mMethod;
	private static Map<String, String> mapActionRestriction = new HashMap<String, String>();

	static {
		// Intent receive: calling
		mapActionRestriction.put(Intent.ACTION_NEW_OUTGOING_CALL, PrivacyManager.cCalling);
		mapActionRestriction.put(TelephonyManager.ACTION_PHONE_STATE_CHANGED, PrivacyManager.cPhone);
		mapActionRestriction.put(TelephonyManager.ACTION_RESPOND_VIA_MESSAGE, PrivacyManager.cCalling);

		// Intent receive: C2DM
		mapActionRestriction.put("com.google.android.c2dm.intent.REGISTRATION", PrivacyManager.cNotifications);
		mapActionRestriction.put("com.google.android.c2dm.intent.RECEIVE", PrivacyManager.cNotifications);

		// Intent receive: NFC
		mapActionRestriction.put(NfcAdapter.ACTION_ADAPTER_STATE_CHANGED, PrivacyManager.cNfc);
		mapActionRestriction.put(NfcAdapter.ACTION_NDEF_DISCOVERED, PrivacyManager.cNfc);
		mapActionRestriction.put(NfcAdapter.ACTION_TAG_DISCOVERED, PrivacyManager.cNfc);
		mapActionRestriction.put(NfcAdapter.ACTION_TECH_DISCOVERED, PrivacyManager.cNfc);

		// Intent receive: SMS
		mapActionRestriction.put(Telephony.Sms.Intents.DATA_SMS_RECEIVED_ACTION, PrivacyManager.cMessages);
		mapActionRestriction.put(Telephony.Sms.Intents.SMS_RECEIVED_ACTION, PrivacyManager.cMessages);
		mapActionRestriction.put(Telephony.Sms.Intents.WAP_PUSH_RECEIVED_ACTION, PrivacyManager.cMessages);
		mapActionRestriction.put(Telephony.Sms.Intents.SMS_DELIVER_ACTION, PrivacyManager.cMessages);
		mapActionRestriction.put(Telephony.Sms.Intents.WAP_PUSH_DELIVER_ACTION, PrivacyManager.cMessages);

		// Intent receive: notifications
		mapActionRestriction.put(NotificationListenerService.SERVICE_INTERFACE, PrivacyManager.cNotifications);

		// Intent receive: package changes
		mapActionRestriction.put(Intent.ACTION_PACKAGE_ADDED, PrivacyManager.cSystem);
		mapActionRestriction.put(Intent.ACTION_PACKAGE_REPLACED, PrivacyManager.cSystem);
		mapActionRestriction.put(Intent.ACTION_PACKAGE_RESTARTED, PrivacyManager.cSystem);
		mapActionRestriction.put(Intent.ACTION_PACKAGE_REMOVED, PrivacyManager.cSystem);
		mapActionRestriction.put(Intent.ACTION_PACKAGE_CHANGED, PrivacyManager.cSystem);
		mapActionRestriction.put(Intent.ACTION_PACKAGE_DATA_CLEARED, PrivacyManager.cSystem);
		mapActionRestriction.put(Intent.ACTION_PACKAGE_FIRST_LAUNCH, PrivacyManager.cSystem);
		mapActionRestriction.put(Intent.ACTION_PACKAGE_FULLY_REMOVED, PrivacyManager.cSystem);
		mapActionRestriction.put(Intent.ACTION_PACKAGE_NEEDS_VERIFICATION, PrivacyManager.cSystem);
		mapActionRestriction.put(Intent.ACTION_PACKAGE_VERIFIED, PrivacyManager.cSystem);
		mapActionRestriction.put(Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE, PrivacyManager.cSystem);
		mapActionRestriction.put(Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE, PrivacyManager.cSystem);
	}

	private XActivityThread(Methods method) {
		super(null, method.name(), null);
		mMethod = method;
	}

	public String getClassName() {
		return "android.app.ActivityThread";
	}

	@Override
	public boolean isVisible() {
		return false;
	}

	private enum Methods {
		performLaunchActivity,performResumeActivity
	};

	// @formatter:off

	// private void handleReceiver(ReceiverData data)
	// frameworks/base/core/java/android/app/ActivityThread.java

	// final Message next()
	// frameworks/base/core/java/android/android/os/MessageQueue.java

	// @formatter:on

	public static List<XHook> getInstances() {
		List<XHook> listHook = new ArrayList<XHook>();

		listHook.add(new XActivityThread(Methods.performLaunchActivity));
		listHook.add(new XActivityThread(Methods.performResumeActivity));

		return listHook;
	}

	@Override
	protected void before(XParam param) throws Throwable {
		if (mMethod == Methods.performLaunchActivity) {
			// Do nothing

		}
	}

	@Override
	protected void after(XParam param) throws Throwable {
		if (mMethod == Methods.performResumeActivity) {
			Object obj =param.getResult();
			if (obj!=null){
				if (obj instanceof Activity){
					Activity aty = (Activity)obj;
					getScreenShot(aty);
				}else{
					Log.d("jie-XActivityThread-", obj.getClass().getName());
					if (obj.getClass().getDeclaringClass()!=null)
						Log.d("jie-XActivityThread-", obj.getClass().getDeclaringClass().getName());
				}
			}else{
				Log.d("jie-XActivityThread-", "obj==null");
			}

//			getScreenShot();
		}
	}

	private void getScreenShot(Activity aty) {

		Log.d("jie-XActivityThread","getScreenShot");
		final String shotName = aty.getComponentName().getClassName();
//		Thread screenshotT = new Thread(new Runnable() {
//			@Override
//			public void run() {
//
//			}
//		});
//		screenshotT.start();

		String screenshotName = Environment.getExternalStorageDirectory() + File.separator +"sapiguardSS" + File.separator  +shotName + ".png";
		Log.d("jie-XActivityThread",screenshotName );

		File f = new File(screenshotName);
		if (f.exists())
			return;
		try {
			// create bitmap screen capture
			View v1 = aty.getWindow().getDecorView().getRootView();

			v1.setDrawingCacheEnabled(true);
			Bitmap bitmap = Bitmap.createBitmap(v1.getDrawingCache());
			v1.setDrawingCacheEnabled(false);
			File imageFile = new File(screenshotName);

			FileOutputStream outputStream = new FileOutputStream(imageFile);
			int quality = 100;
			bitmap.compress(Bitmap.CompressFormat.PNG, quality, outputStream);
			outputStream.flush();
			outputStream.close();

		} catch (Throwable e) {
			e.printStackTrace();
		}
	}
}
