package com.tcl.factory.utils;

import java.util.List;

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.util.Log;

import com.tcl.factory.thirdparty.ThirdParty;

public class AppManagementHandler {
    private String mTag = "app_management";
    private boolean showLog = false;
    private final int delayTime = 1000;//measure in milliseconds
    private Context mContext;

    public AppManagementHandler(Context context, String accessKey) {
        this(context, accessKey, null);
    }

    public AppManagementHandler(Context context, String accessKey, String tag) {
        this.mContext = context;
        if (tag != null && tag.trim().length() != 0) {
            this.mTag = tag;
        }
    }

    public void disableApps(List<String> appInfos) {
        Log.i(mTag, "disable package2:(" + appInfos.size() + ")" + appInfos.toString());
        int size = appInfos.size();
        for (int i = 0; i < size; i++) {
            final String packageName = appInfos.get(i);
            Log.i(mTag, i + ":start:disable package(" + packageName);
            Boolean result = disableApp(packageName);
            if (result == null) {
                Log.i(mTag, "disable package(" + packageName + ") has exception");
            } else {
                Log.i(mTag, "disable package(" + packageName + ") " + (result.booleanValue() ? "success" : "fail"));
            }
            try {
                Thread.sleep(delayTime);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
//		Iterator<String> iterator = appInfos.iterator();
//		while(iterator.hasNext()){
//			String packageName = iterator.next();
//			Log.i(mTag, "start:disable package("+packageName);
//			Boolean result =disableApp(packageName);
//			if(result==null){
//				Log.i(mTag, "disable package("+packageName+") has exception");
//			}else{
//				Log.i(mTag, "disable package("+packageName+") "+(result.booleanValue()?"success":"fail"));
//			}
//		}
        Log.i(mTag, "end:disable package---------");
    }

    public void enableApps(List<String> appInfos) {
        Log.i(mTag, "enable package2:(" + appInfos.size() + ")" + appInfos.toString());
        int size = appInfos.size();
        for (int i = 0; i < size; i++) {
            final String packageName = appInfos.get(i);
            Log.i(mTag, i + ":start:enable package(" + packageName);
            Boolean result = enableApp(packageName);
            if (result == null) {
                Log.i(mTag, "enable package(" + packageName + ") has exception");
            } else {
                Log.i(mTag, "enable package(" + packageName + ") " + (result.booleanValue() ? "success" : "fail"));
            }
            try {
                Thread.sleep(delayTime);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
//		Iterator<String> iterator = appInfos.iterator();
//		while(iterator.hasNext()){
//			String packageName = iterator.next();
//			Log.i(mTag, "start:enable package("+packageName);
//			Boolean result =enableApp(packageName);
//			if(result==null){
//				Log.i(mTag, "enable package("+packageName+") has exception");
//			}else{
//				Log.i(mTag, "enable package("+packageName+") "+(result.booleanValue()?"success":"fail"));
//			}
//		}	
        Log.i(mTag, "end:enable package---------");
    }


    public Boolean enableApp(String packageName) {
        if (packageName == null || packageName.trim().length() == 0) {
            if (isShowLog()) {
                Log.w(mTag, "package name must be not empty!");
            }
            return null;
        }
        //if APP is disable or hide ,it can not be find
//		if(!isAppExists(mContext,packageName)){
//			if(isShowLog()){
//				Log.w(mTag,"package name must be not empty!");
//			}
//			return null ;
//		}
        String cmdStr = createHideCommandString(packageName, type_unhide);
        Boolean ret =ThirdParty.setRootSeek(cmdStr);
        if (isShowLog()) {
            Log.w(mTag, "commond:[" + cmdStr + "],result:" + ret);
        }
        return ret;
    }

    public Boolean disableApp(String packageName) {
        if (packageName == null || packageName.trim().length() == 0) {
            if (isShowLog()) {
                Log.w(mTag, "package name must be not empty!");
            }
            return null;
        }
//		if(!isAppExists(mContext,packageName)){
//			if(isShowLog()){
//				Log.w(mTag,"package name must be not empty!");
//			}
//			return null ;
//		}
        String cmdStr = createHideCommandString(packageName, type_hide);
        Boolean ret =ThirdParty.setRootSeek(cmdStr);
        if (isShowLog()) {
            Log.w(mTag, "commond:[" + cmdStr + "],result:" + ret);
        }
        return ret;
    }

    public Boolean hideApp(String packageName) {
        if (packageName == null || packageName.trim().length() == 0) {
            if (isShowLog()) {
                Log.w(mTag, "package name must be not empty!");
            }
            return null;
        }
//		if(!isAppExists(mContext,packageName)){
//			if(isShowLog()){
//				Log.w(mTag,"package name must be not empty!");
//			}
//			return null ;
//		}
        String cmdStr = createHideCommandString(packageName, type_disable);
        Boolean ret =ThirdParty.setRootSeek(cmdStr);
        if (isShowLog()) {
            Log.w(mTag, "commond:[" + cmdStr + "],result:" + ret);
        }
        return ret;
    }

    public Boolean deleteApp(String packageName) {
        if (packageName == null || packageName.trim().length() == 0) {
            if (isShowLog()) {
                Log.w(mTag, "package name must be not empty!");
            }
            return null;
        }
        if (!isAppExists(mContext, packageName)) {
            if (isShowLog()) {
                Log.w(mTag, "package name must be not empty!");
            }
            return null;
        }
        if (!isAppUninstall(mContext, packageName)) {
            if (isShowLog()) {
                Log.w(mTag, "package(" + packageName + ") can be delete");
            }
            return null;
        }
        String cmdStr = createHideCommandString(packageName, type_delete);
        Boolean ret =ThirdParty.setRootSeek(cmdStr);
        if (isShowLog()) {
            Log.w(mTag, "commond:[" + cmdStr + "],result:" + ret);
        }
        return ret;
    }

    private String createHideCommandString(String packageName, int type) {
        if (type == type_hide) {
            return "pm hide " + packageName;
        } else if (type == type_unhide) {
            return "pm unhide " + packageName;
        } else if (type == type_delete) {
            return "pm uninstall " + packageName;
        } else if (type == type_disable) {
            return "pm disable " + packageName;
        } else if (type == type_enable) {
            return "pm enable " + packageName;
        } else {
            return "";
        }
    }

    private boolean isAppExists(Context context, String packageName) {
        PackageManager packageManager = context.getPackageManager();
        try {
            packageManager.getPackageInfo(packageName, 0);
            return true;
        } catch (NameNotFoundException e) {
            e.printStackTrace();
            if (isShowLog()) {
                Log.w(mTag, "package(" + packageName + ") is not exists");
            }
        }
        return false;
    }

    private boolean isAppUninstall(Context context, String packageName) {
        PackageManager packageManager = context.getPackageManager();
        try {
            PackageInfo info = packageManager.getPackageInfo(packageName, 0);
            boolean isSystemApp = (info.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) == 1;
            boolean isUpdateSystemApp = (info.applicationInfo.flags & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) == 1;
            if (!isSystemApp || isUpdateSystemApp) {
                return true;
            } else {
                return false;
            }
        } catch (NameNotFoundException e) {
            if (isShowLog()) {
                Log.w(mTag, "package(" + packageName + ") is not exists");
            }
            e.printStackTrace();
        }
        return false;
    }

    public boolean isShowLog() {
        return showLog;
    }

    public void setShowLog(boolean showLog) {
        this.showLog = showLog;
    }

    private final int type_hide = 1;
    private final int type_unhide = 2;
    private final int type_delete = 3;
    private final int type_disable = 4;
    private final int type_enable = 5;
}
