package com.gh.common.util;

import android.content.Context;
import android.content.Intent;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.pm.Signature;
import android.net.Uri;
import android.os.Bundle;
import android.support.v4.util.ArrayMap;
import android.text.TextUtils;
import android.util.DisplayMetrics;
import android.widget.Toast;

import com.gh.gamecenter.manager.FilterManager;

import java.io.ByteArrayInputStream;
import java.io.File;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.List;

public class PackageUtils {
	
	public static final String publicKey = "OpenSSLRSAPublicKey{modulus=a8c4bb5748fec8d5c35db1a7a182d41ba4721a91131a417330af79ef4ddb43f9fa0ff4907b0a613bfe152de0ed8fc1b2e6f94a908aa98a5f7adc1ce814ba7ec919d75d9910bdfd8649b4789da6a90ffb61f0d23ac4f828a78fcd0d6f6120c1c43c1f87f7498a89eb40ca8e32dfc2f9d5c10d612b95192870223674e241e53305abf320d7eed76ded398778576e4db7b17b3bc6a792f13de5e43a6a5fae4276c73e6990ce97f68dff0ec16fc9594f175c8d49cd0d7877340d9de60942ca0efc737e50b6c295dfe0713e4532b4e810e1ea11b702b4a27753e41559cbceb247e7f044ec4e3ab2e8bccd8b9fd71286e63307550bcde86deee95adb8133076269135b,publicExponent=10001}";

	/*
	 * 根据apk路径，获取apk的签名信息,耗时
	 */
	@SuppressWarnings({ "rawtypes", "unchecked" })
	public static String getApkSignatureByPath(Context context, String path) {
		String PATH_PackageParser = "android.content.pm.PackageParser";
		try {
			// apk包的文件路径
			// 这是一个Package 解释器, 是隐藏的
			// 构造函数的参数只有一个, apk文件的路径
			// PackageParser packageParser = new PackageParser(apkPath);
			Class pkgParserCls = Class.forName(PATH_PackageParser);
			Class[] typeArgs = new Class[1];
			typeArgs[0] = String.class;
			Constructor pkgParserCt = pkgParserCls.getConstructor(typeArgs);
			Object[] valueArgs = new Object[1];
			valueArgs[0] = path;
			Object pkgParser = pkgParserCt.newInstance(valueArgs);
			// 这个是与显示有关的, 里面涉及到一些像素显示等等, 我们使用默认的情况
			DisplayMetrics metrics = new DisplayMetrics();
			metrics.setToDefaults();
			// PackageParser.Package mPkgInfo = packageParser.parsePackage(new
			// File(apkPath), apkPath,
			// metrics, 0);
			typeArgs = new Class[4];
			typeArgs[0] = File.class;
			typeArgs[1] = String.class;
			typeArgs[2] = DisplayMetrics.class;
			typeArgs[3] = Integer.TYPE;
			Method pkgParser_parsePackageMtd = pkgParserCls.getDeclaredMethod(
					"parsePackage", typeArgs);
			valueArgs = new Object[4];
			valueArgs[0] = new File(path);
			valueArgs[1] = path;
			valueArgs[2] = metrics;
			valueArgs[3] = PackageManager.GET_SIGNATURES;
			Object pkgParserPkg = pkgParser_parsePackageMtd.invoke(pkgParser,
					valueArgs);

			typeArgs = new Class[2];
			typeArgs[0] = pkgParserPkg.getClass();
			typeArgs[1] = Integer.TYPE;
			Method pkgParser_collectCertificatesMtd = pkgParserCls
					.getDeclaredMethod("collectCertificates", typeArgs);
			valueArgs = new Object[2];
			valueArgs[0] = pkgParserPkg;
			valueArgs[1] = PackageManager.GET_SIGNATURES;
			pkgParser_collectCertificatesMtd.invoke(pkgParser, valueArgs);
			// 应用程序信息包, 这个公开的, 不过有些函数, 变量没公开
			Field packageInfoFld = pkgParserPkg.getClass().getDeclaredField(
					"mSignatures");
			Signature[] info = (Signature[]) packageInfoFld.get(pkgParserPkg);
			return parseSignature(info[0].toByteArray())[0];
		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;
	}

	/*
	 * 根据路径，获取apk的包名
	 */
	public static String getPackageNameByPath(Context context, String path) {
		PackageManager packageManager = context.getPackageManager();
		PackageInfo info = packageManager.getPackageArchiveInfo(path,
				PackageManager.GET_ACTIVITIES);
		if (info != null) {
			ApplicationInfo appInfo = info.applicationInfo;
			return appInfo.packageName;
		}
		return null;
	}

	public static Object getMetaData(Context context, String packageName, String name) {
		try {
			Bundle metaDate = context.getPackageManager().getApplicationInfo(
					packageName, PackageManager.GET_META_DATA).metaData;
			if (metaDate != null) {
				return metaDate.get(name);
			}
		} catch (NameNotFoundException e) {
			e.printStackTrace();
		}
		return null;
	}

	/*
	 * 根据包名，获取apk的签名信息
	 */
	public static String getApkSignatureByPackageName(Context context,
			String packageName) {
		try {
			PackageInfo packageInfo = context.getPackageManager()
					.getPackageInfo(packageName, PackageManager.GET_SIGNATURES);
			Signature[] signatures = packageInfo.signatures;
			return parseSignature(signatures[0].toByteArray())[0];
		} catch (NameNotFoundException e) {
			e.printStackTrace();
		}
		return null;
	}

	/*
	 * 判断是否是插件包
	 */
	public static boolean isSignature(Context context, String packageName) {
		String signature = getApkSignatureByPackageName(context, packageName);
		if (publicKey.equals(signature)) {
			return true;
		}
		return false;
	}

	/**
	 * 根据apk路径，获取apk包名、签名 根据包名 判断 是否已安装游戏 根据签名 判断 是否一致
	 *
	 * @param path apk路径
	 * @return true 可执行安装 false 要卸载已安装的，再执行安装
	 */
	public static boolean isCanLaunchSetup(Context context, String path) {
		String packageName = getPackageNameByPath(context, path);

		boolean isContain = isContain(context, packageName);
		if (!isContain) {
			return true;
		}

		boolean isInstalled = isInstalled(context, packageName);
		if (!isInstalled) {
			return true;
		}

		String signature = getApkSignatureByPackageName(context, packageName);
		return publicKey.equals(signature);
	}

	/*
	 * 启动安装应用程序
	 */
	public static void launchSetup(final Context context, final String path) {
		if (isCanLaunchSetup(context, path)) {
			context.startActivity(PackageUtils.getInstallIntent(path));
		} else {
			DialogUtils.showPluginDialog(context, new DialogUtils.ConfiremListener() {
				@Override
				public void onConfirem() {
					context.startActivity(PackageUtils.getUninstallIntent(context, path));
				}
			});
		}
	}

	/*
	 * 获取应用第一次安装的时间
	 */
	public static long getInstalledTime(Context context, String packageName) {
		try {
			PackageInfo packageInfo = context.getPackageManager()
					.getPackageInfo(packageName, 0);
			return packageInfo.firstInstallTime;
		} catch (NameNotFoundException e) {
			e.printStackTrace();
		}
		return 0;
	}

	/*
	 * 解析签名
	 */
	private static String[] parseSignature(byte[] signature) {
		String[] ret = null;
		try {
			CertificateFactory certFactory = CertificateFactory
					.getInstance("X.509");
			X509Certificate cert = (X509Certificate) certFactory
					.generateCertificate(new ByteArrayInputStream(signature));
			ret = new String[] { cert.getPublicKey().toString(),
					cert.getSerialNumber().toString() };
		} catch (CertificateException e) {
			e.printStackTrace();
		}
		return ret;
	}

	/*
	 * 返回光环助手的版本信息
	 */
	public static String getVersion(Context context) {
		try {
			PackageInfo pkgInfo = context.getPackageManager().getPackageInfo(
					context.getPackageName(), 0);
			return pkgInfo.versionName;
		} catch (NameNotFoundException e) {
			e.printStackTrace();
		}
		return null;
	}

	public static String getVersionByPackage(Context context, String packageName) {
		try {
			return context.getPackageManager().getPackageInfo(packageName,
					PackageManager.COMPONENT_ENABLED_STATE_DEFAULT).versionName;
		} catch (NameNotFoundException e) {
			e.printStackTrace();
		}
		return null;
	}

	/**
	 * 获取所有已安装的软件的包名、版本(非系统应用)
	 *
	 * @param context
	 *            上下文
	 * @return 已安装软件的包名的集合
	 */
	public static ArrayList<String> getAllPackageName(Context context) {
		FilterManager filterManager = new FilterManager(context);
		ArrayList<String> list = new ArrayList<>();
		List<PackageInfo> packageInfos = context.getPackageManager()
				.getInstalledPackages(0);
		for (int i = 0, size = packageInfos.size(); i < size; i++) {
			PackageInfo packageInfo = packageInfos.get(i);
			if ((packageInfo.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) == 0) {
				if (!context.getPackageName().equals(packageInfo.packageName)) {
					if (!filterManager.isFilter(packageInfo.packageName)) {
						list.add(packageInfo.packageName);
					}
				}
			}
		}
		return list;
	}

	public static void launchApplicationByPackageName(Context context,
			String packageName) {
		Intent intent = context.getPackageManager().getLaunchIntentForPackage(
				packageName);
		if (intent != null) {
			context.startActivity(intent);
		} else {
			Toast.makeText(context, "启动失败", Toast.LENGTH_SHORT).show();
		}
	}

	/*
	 * 根据包名，获取软件名称
	 */
	public static String getNameByPackageName(Context context,
			String packageName) {
		try {
			PackageManager pm = context.getPackageManager();
			ApplicationInfo applicationInfo = pm.getApplicationInfo(
					packageName, 0);
			return applicationInfo.loadLabel(pm).toString();
		} catch (NameNotFoundException e) {
			e.printStackTrace();
		}
		return null;
	}

	/*
	 * 根据包名，判断是否已安装该游戏
	 */
	public static boolean isInstalled(Context context, String packageName) {
		Intent intent = context.getPackageManager().getLaunchIntentForPackage(
				packageName);
		if (intent == null) {
			return false;
		}
		return true;
	}

	private static ArrayMap<String, Boolean> map;

	public static boolean isContain(Context context, String packageName) {
		if (TextUtils.isEmpty(packageName)) {
			return false;
		}
		if (map == null) {
			map = new ArrayMap<>();
			List<PackageInfo> infos = context.getPackageManager()
					.getInstalledPackages(0);
			for (PackageInfo info : infos) {
				map.put(info.packageName, true);
			}
		}
		Boolean b = map.get(packageName);
		if (b != null) {
			return true;
		}
		return false;
	}

	/*
	 * 根据包名，获取卸载游戏的意图
	 */
	public static Intent getUninstallIntent(Context context, String path) {
		Intent uninstallIntent = new Intent();
		uninstallIntent.setAction("android.intent.action.DELETE");
		uninstallIntent.addCategory("android.intent.category.DEFAULT");
		uninstallIntent.setData(Uri.parse("package:"
				+ getPackageNameByPath(context, path)));
		return uninstallIntent;
	}

	/*
	 * 根据路径，获取安装游戏的意图
	 */
	public static Intent getInstallIntent(String path) {
		Uri uri = Uri.fromFile(new File(path));
		Intent installIntent = new Intent(Intent.ACTION_VIEW);
		installIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
		installIntent.setDataAndType(uri,
				"application/vnd.android.package-archive");
		return installIntent;
	}

	public static String getInstalledApkPath(Context context, String packageName) {
		try {
			return context.getPackageManager().getApplicationInfo(packageName,
					0).sourceDir;
		} catch (NameNotFoundException e) {
			e.printStackTrace();
		}
		return null;
	}
}
