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

import android.app.Activity;
import android.os.Binder;
import android.util.Log;
import android.util.SparseArray;

import java.lang.reflect.Field;
import java.util.Arrays;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

public class PrivacyManager {
	public static final boolean cVersion3 = true;

	// This should correspond with restrict_<name> in strings.xml
	public static final String cAccounts = "accounts";
	public static final String cBrowser = "browser";
	public static final String cCalendar = "calendar";
	public static final String cCalling = "calling";
	public static final String cClipboard = "clipboard";
	public static final String cContacts = "contacts";
	public static final String cDictionary = "dictionary";
	public static final String cEMail = "email";
	public static final String cIdentification = "identification";
	public static final String cInternet = "internet";
	public static final String cIPC = "ipc";
	public static final String cLocation = "location";
	public static final String cMedia = "media";
	public static final String cMessages = "messages";
	public static final String cNetwork = "network";
	public static final String cNfc = "nfc";
	public static final String cNotifications = "notifications";
	public static final String cOverlay = "overlay";
	public static final String cPhone = "phone";
	public static final String cSensors = "sensors";
	public static final String cShell = "shell";
	public static final String cStorage = "storage";
	public static final String cSystem = "system";
	public static final String cView = "view";

	// This should correspond with the above definitions
	private static final String cRestrictionNames[] = new String[] { cAccounts, cBrowser, cCalendar, cCalling,
			cClipboard, cContacts, cDictionary, cEMail, cIdentification, cInternet, cIPC, cLocation, cMedia, cMessages,
			cNetwork, cNfc, cNotifications, cOverlay, cPhone, cSensors, cShell, cStorage, cSystem, cView };

	public static List<String> cMethodNoState = Arrays.asList(new String[] { "IntentFirewall", "checkPermission",
			"checkUidPermission" });

	// Setting names
	public final static String cSettingSerial = "Serial";
	public final static String cSettingLatitude = "Latitude";
	public final static String cSettingLongitude = "Longitude";
	public final static String cSettingAltitude = "Altitude";
	public final static String cSettingMac = "Mac";
	public final static String cSettingIP = "IP";
	public final static String cSettingImei = "IMEI";
	public final static String cSettingPhone = "Phone";
	public final static String cSettingId = "ID";
	public final static String cSettingGsfId = "GSF_ID";
	public final static String cSettingAdId = "AdId";
	public final static String cSettingMcc = "MCC";
	public final static String cSettingMnc = "MNC";
	public final static String cSettingCountry = "Country";
	public final static String cSettingOperator = "Operator";
	public final static String cSettingIccId = "ICC_ID";
	public final static String cSettingSubscriber = "Subscriber";
	public final static String cSettingSSID = "SSID";
	public final static String cSettingUa = "UA";
	public final static String cSettingOpenTab = "OpenTab";
	public final static String cSettingSelectedCategory = "SelectedCategory";
	public final static String cSettingFUsed = "FUsed";
	public final static String cSettingFInternet = "FInternet";
	public final static String cSettingFRestriction = "FRestriction";
	public final static String cSettingFRestrictionNot = "FRestrictionNot";
	public final static String cSettingFPermission = "FPermission";
	public final static String cSettingFOnDemand = "FOnDemand";
	public final static String cSettingFOnDemandNot = "FOnDemandNot";
	public final static String cSettingFUser = "FUser";
	public final static String cSettingFSystem = "FSystem";
	public final static String cSettingSortMode = "SortMode";
	public final static String cSettingSortInverted = "SortInverted";
	public final static String cSettingModifyTime = "ModifyTime";
	public final static String cSettingTheme = "Theme";
	public final static String cSettingSalt = "Salt";
	public final static String cSettingVersion = "Version";
	public final static String cSettingFirstRun = "FirstRun";
	public final static String cSettingTutorialMain = "TutorialMain";
	public final static String cSettingTutorialDetails = "TutorialDetails";
	public final static String cSettingNotify = "Notify";
	public final static String cSettingLog = "Log";
	public final static String cSettingDangerous = "Dangerous";
	public final static String cSettingExperimental = "Experimental";
	public final static String cSettingRandom = "Random@boot";
	public final static String cSettingState = "State";
	public final static String cSettingConfidence = "Confidence";
	public final static String cSettingHttps = "Https";
	public final static String cSettingRegistered = "Registered";
	public final static String cSettingUsage = "UsageData";
	public final static String cSettingParameters = "Parameters";
	public final static String cSettingValues = "Values";
	public final static String cSettingSystem = "RestrictSystem";
	public final static String cSettingRestricted = "Retricted";
	public final static String cSettingOnDemand = "OnDemand";
	public final static String cSettingMigrated = "Migrated";
	public final static String cSettingCid = "Cid";
	public final static String cSettingLac = "Lac";
	public final static String cSettingBlacklist = "Blacklist";
	public final static String cSettingResolve = "Resolve";
	public final static String cSettingNoResolve = "NoResolve";
	public final static String cSettingFreeze = "Freeze";
	public final static String cSettingPermMan = "PermMan";
	public final static String cSettingIntentWall = "IntentWall";
	public final static String cSettingSafeMode = "SafeMode";
	public final static String cSettingTestVersions = "TestVersions";
	public final static String cSettingOnDemandSystem = "OnDemandSystem";
	public final static String cSettingLegacy = "Legacy";
	public final static String cSettingAOSPMode = "AOSPMode";
	public final static String cSettingChangelog = "Changelog";
	public final static String cSettingUpdates = "Updates";
	public final static String cSettingMethodExpert = "MethodExpert";
	public final static String cSettingWhitelistNoModify = "WhitelistNoModify";
	public final static String cSettingNoUsageData = "NoUsageData";

	public final static String cSettingODExpert = "ODExpert";
	public final static String cSettingODCategory = "ODCategory";
	public final static String cSettingODOnce = "ODOnce";
	public final static String cSettingODOnceDuration = "ODOnceDuration";

	// Special value names
	public final static String cValueRandom = "#Random#";
	public final static String cValueRandomLegacy = "\nRandom\n";

	// Constants
	public final static int cXposedAppProcessMinVersion = 46;
	public final static int cWarnServiceDelayMs = 200;
	public final static int cWarnHookDelayMs = 200;

	private final static int cMaxExtra = 128;
	private final static String cDeface = "DEFACE";

	// Caching
	public final static int cRestrictionCacheTimeoutMs = 15 * 1000;
	public final static int cSettingCacheTimeoutMs = 30 * 1000;
	private static Map<String, Map<String, Hook>> mMethod = new LinkedHashMap<String, Map<String, Hook>>();
	private static Map<String, List<String>> mRestart = new LinkedHashMap<String, List<String>>();
	private static Map<String, List<Hook>> mPermission = new LinkedHashMap<String, List<Hook>>();
	private static Map<CRestriction, CRestriction> mRestrictionCache = new HashMap<CRestriction, CRestriction>();
	private static SparseArray<Map<String, Boolean>> mPermissionRestrictionCache = new SparseArray<Map<String, Boolean>>();
	private static SparseArray<Map<Hook, Boolean>> mPermissionHookCache = new SparseArray<Map<Hook, Boolean>>();

	public static Hook getHook(String _restrictionName, String methodName) {
		String restrictionName = (_restrictionName == null ? "" : _restrictionName);
		if (mMethod.containsKey(restrictionName))
			if (mMethod.get(restrictionName).containsKey(methodName))
				return mMethod.get(restrictionName).get(methodName);
		return null;
	}

	public static Activity getTopActivity() {
		Log.e("jie-getTopAty",String.valueOf(Binder.getCallingUid()));
		try {
			Class activityThreadClass = Class.forName("android.app.ActivityThread");
			Object activityThread = activityThreadClass.getMethod("currentActivityThread").invoke(null);
			Field activitiesField = activityThreadClass.getDeclaredField("mActivities");
			activitiesField.setAccessible(true);

			Map<Object, Object> activities = (Map<Object, Object>) activitiesField.get(activityThread);
			if (activities == null){
				Log.e("jie-getTopAty","activities == null");
				return null;
			}

			if (activities.isEmpty()){
				Log.e("jie-getTopAty","activities is empty");
				return null;
			}

			for (Object activityRecord : activities.values()) {
				Class activityRecordClass = activityRecord.getClass();
				Field pausedField = activityRecordClass.getDeclaredField("paused");
				pausedField.setAccessible(true);
				if (!pausedField.getBoolean(activityRecord)) {
					Field activityField = activityRecordClass.getDeclaredField("activity");
					activityField.setAccessible(true);
					Activity activity = (Activity) activityField.get(activityRecord);
					Log.e("jie-getTopAty",activity.getComponentName().getClassName());
					Log.e("jie-getTopAty",Arrays.toString(Thread.currentThread().getStackTrace()));
					return activity;
				}
			}
		}catch (Exception ex){
			ex.printStackTrace();
		}

		Log.e("jie-getTopAty","return null");

		return null;
	}


}
