package com.mjsheng.myappstore.utils;

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.net.Uri;
import android.os.Binder;
import android.os.Build;
import android.support.v4.content.FileProvider;
import android.util.Log;
import android.view.View;
import android.widget.Toast;


import com.lzy.okserver.download.DownloadInfo;
import com.lzy.okserver.download.DownloadManager;
import com.lzy.okserver.download.DownloadService;
import com.mjsheng.myappstore.R;
import com.mjsheng.myappstore.bean.AppDateInfo;
import com.mjsheng.myappstore.bean.AppDownloadInfo;
import com.mjsheng.myappstore.download.StorageUtils;
import com.mjsheng.myappstore.utils.update.ToastTool;

import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;

import rx.Observable;
import rx.Observer;
import rx.Subscriber;
import rx.android.schedulers.AndroidSchedulers;
import rx.schedulers.Schedulers;

public class ApkUtils {


    public static synchronized boolean getRootAhth() {
        Process process = null;
        DataOutputStream os = null;
        try {
            process = Runtime.getRuntime().exec("su");
            os = new DataOutputStream(process.getOutputStream());
            os.writeBytes("exit\n");
            os.flush();
            int exitValue = process.waitFor();
            if (exitValue == 0) {
                return true;
            } else {
                return false;
            }
        } catch (Exception e) {
            Log.e("*** DEBUG ***", "Unexpected error - Here is what I know: "
                    + e.getMessage());
            return false;
        } finally {
            try {
                if (os != null) {
                    os.close();
                }
                process.destroy();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    public static void openApp(Context context, View view) {
        try {
            Intent intent = context.getPackageManager().getLaunchIntentForPackage((String) view.getTag(R.string.download_btn_had));
            context.startActivity(intent);
        } catch (Exception e) {
            Toast.makeText(context, R.string.open_app_fail, Toast.LENGTH_LONG).show();
        }
        return;
    }

    /**
     * 安装一个apk文件
     */
    public static void install(Context context, File uriFile) {

        Intent intent = new Intent(Intent.ACTION_VIEW);
        // 由于没有在Activity环境下启动Activity,设置下面的标签
        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        if (Build.VERSION.SDK_INT >= 24) { //判读版本是否在7.0以上
            //参数1 上下文, 参数2 Provider主机地址 和配置文件中保持一致   参数3  共享的文件
            Uri apkUri =
                    FileProvider.getUriForFile(context, "com.jiaoguanyi.appstore.fileprovider", uriFile);
            //添加这一句表示对目标应用临时授权该Uri所代表的文件
            intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
            intent.setDataAndType(apkUri, "application/vnd.android.package-archive");
        } else {
            intent.setDataAndType(Uri.fromFile(uriFile),
                    "application/vnd.android.package-archive");
        }
        context.startActivity(intent);
    }

    /**
     * 卸载一个app
     */
    public static void uninstall(Context context, String packageName) {
        //通过程序的包名创建URI
        Uri packageURI = Uri.parse("package:" + packageName);
        //创建Intent意图
        Intent intent = new Intent(Intent.ACTION_DELETE, packageURI);
        //执行卸载程序
        context.startActivity(intent);
    }

    /**
     * 检查手机上是否安装了指定的软件
     */
    public static boolean isAvailable(Context context, String packageName) {
        // 获取packagemanager
        final PackageManager packageManager = context.getPackageManager();
        // 获取所有已安装程序的包信息
        List<PackageInfo> packageInfos = packageManager.getInstalledPackages(0);
        // 用于存储所有已安装程序的包名
        List<String> packageNames = new ArrayList<>();
        // 从pinfo中将包名字逐一取出，压入pName list中
        if (packageInfos != null) {
            for (int i = 0; i < packageInfos.size(); i++) {
                String packName = packageInfos.get(i).packageName;
                packageNames.add(packName);
            }
        }
        // 判断packageNames中是否有目标程序的包名，有TRUE，没有FALSE
        return packageNames.contains(packageName);
    }

    /**
     * 检查手机上是否安装了指定的软件
     */
    public static boolean isAvailable(Context context, File file) {
        return isAvailable(context, getPackageName(context, file.getAbsolutePath()));
    }

    /**
     * 根据文件路径获取包名
     */
    public static String getPackageName(Context context, String filePath) {
        PackageManager packageManager = context.getPackageManager();
        PackageInfo info = packageManager.getPackageArchiveInfo(filePath, PackageManager.GET_ACTIVITIES);
        if (info != null) {
            ApplicationInfo appInfo = info.applicationInfo;
            return appInfo.packageName;  //得到安装包名称
        }
        return null;
    }

    /**
     * 从apk中获取版本信息
     */
    public static String getChannelFromApk(Context context, String channelPrefix) {
        //从apk包中获取
        ApplicationInfo appinfo = context.getApplicationInfo();
        String sourceDir = appinfo.sourceDir;
        //默认放在meta-inf/里， 所以需要再拼接一下
        String key = "META-INF/" + channelPrefix;
        String ret = "";
        ZipFile zipfile = null;
        try {
            zipfile = new ZipFile(sourceDir);
            Enumeration<?> entries = zipfile.entries();
            while (entries.hasMoreElements()) {
                ZipEntry entry = ((ZipEntry) entries.nextElement());
                String entryName = entry.getName();
                if (entryName.startsWith(key)) {
                    ret = entryName;
                    break;
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (zipfile != null) {
                try {
                    zipfile.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        String[] split = ret.split(channelPrefix);
        String channel = "";
        if (split.length >= 2) {
            channel = ret.substring(key.length());
        }
        return channel;
    }


    public static void installRx(final Context context, final String packageName, final String filePath) {

        Observable.create(new Observable.OnSubscribe<Integer>() {
            @Override
            public void call(Subscriber<? super Integer> subscriber) {
                File file = new File(filePath);
                if (filePath == null || filePath.length() == 0 || file == null) {
                    Log.e("mjsheng", "errormesg=========" + "   空啊 ");
                    subscriber.onNext(0);
                    return;
                }
                //                                String[] args = { "pm", "install", "-r", filePath };
                String[] args = {"pm", "install", "-i", "com.colorflykids", "--user", "0", filePath};
                //                String argss = "pm install -i " + "com.colorflykids" + " --user 0 " + filePath;
                Log.e("mjsheng", "argss====" + args);
                ProcessBuilder processBuilder = new ProcessBuilder(args);
                Process process = null;
                BufferedReader successResult = null;
                BufferedReader errorResult = null;
                StringBuilder successMsg = new StringBuilder();
                StringBuilder errorMsg = new StringBuilder();
                try {
                    process = processBuilder.start();
                    successResult = new BufferedReader(new InputStreamReader(process.getInputStream()));
                    errorResult = new BufferedReader(new InputStreamReader(process.getErrorStream()));
                    String s;
                    while ((s = successResult.readLine()) != null) {
                        Log.e("mjhseng", "successResult----------" + s);
                        successMsg.append(s);
                    }
                    while ((s = errorResult.readLine()) != null) {
                        Log.e("mjhseng", "errorResult----------" + s);
                        errorMsg.append(s);
                    }
                } catch (IOException e1) {
                    Log.e("mjsheng", "IOException e1)----------" + e1.toString());
                    e1.printStackTrace();
                } finally {
                    try {
                        if (successResult != null) {
                            successResult.close();
                        }
                        if (errorResult != null) {
                            errorResult.close();
                        }
                    } catch (IOException e1) {
                        Log.e("mjsheng", "IOException e11)---------" + e1.toString());
                        e1.printStackTrace();
                    }
                    if (process != null) {
                        process.destroy();
                    }
                }
                if (successMsg.toString().contains("Success") || successMsg.toString().contains("success")) {
                    subscriber.onNext(2);
                } else {
                    Log.e("mjsheng", "errormesg=========" + errorMsg.toString());
                    subscriber.onNext(1);
                }
            }
        }).subscribeOn(Schedulers.newThread())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new Observer<Integer>() {

                    @Override
                    public void onNext(Integer value) {
                        if (value == 2) {
                            //安装成功
                            Utils.showToast(context, "安装成功");
                            Log.e("mjsheng", "-----------安装成功-----------");
                        } else {
                            //安装错误
                            Log.e("mjsheng", "------------安装错误-----------");
                            Utils.showToast(context, "安装失败");
                        }
                    }

                    @Override
                    public void onCompleted() {

                    }

                    @Override
                    public void onError(Throwable e) {
                        //安装错误
                    }
                });
    }

    //    public static void installApp(final String path, final String packageNames){
    //        File apkFile = new File(path);
    //        try {
    //            Class<?> clazz = Class.forName("android.os.ServiceManager");
    //            Method method_getService = clazz.getMethod("getService", String.class);
    //            IBinder bind = (IBinder) method_getService.invoke(null, "package");
    //            IPackageManager iPm = IPackageManager.Stub.asInterface(bind);
    //            iPm.installPackage(Uri.fromFile(apkFile),null, 2, apkFile.getName());
    //            Log.e("mjsheng", "安装成功");
    //        } catch (Exception e) {
    //            e.printStackTrace();
    //            Log.e("mjsheng", "安装失败");
    //        }
    //    }


    public static void installApkInSilence(String installPath, String packageName) {
        ToastTool.show("正在安装应用...");
        setInstallIngPackageName(packageName);
        Class<?> pmService;
        Class<?> activityTherad;
        Method method;
        try {
            activityTherad = Class.forName("android.app.ActivityThread");
            Class<?> paramTypes[] = getParamTypes(activityTherad, "getPackageManager");
            method = activityTherad.getMethod("getPackageManager", paramTypes);
            Object PackageManagerService = method.invoke(activityTherad);
            pmService = PackageManagerService.getClass();
            Class<?> paramTypes1[] = getParamTypes(pmService, "installPackageAsUser");
            method = pmService.getMethod("installPackageAsUser", paramTypes1);
            method.invoke(PackageManagerService, installPath, null, 0x00000040, packageName, getUserId(Binder.getCallingUid()));//getUserId
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
            Log.e("installApkInSilence", "ClassNotFoundException:" + e.getMessage());
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
            Log.e("installApkInSilence", "NoSuchMethodException:" + e.getMessage());
        } catch (IllegalAccessException e) {
            e.printStackTrace();
            Log.e("installApkInSilence", "IllegalAccessException:" + e.getMessage());
        } catch (InvocationTargetException e) {
            e.printStackTrace();
            Log.e("installApkInSilence", "InvocationTargetException:" + e.getMessage());
        }
    }

    public static void deleteApkInSilence(String packageName) {
        Class<?> pmService;
        Class<?> activityTherad;
        Method method;
        try {
            activityTherad = Class.forName("android.app.ActivityThread");
            Class<?> paramTypes[] = getParamTypes(activityTherad, "getPackageManager");
            method = activityTherad.getMethod("getPackageManager", paramTypes);
            Object PackageManagerService = method.invoke(activityTherad);
            pmService = PackageManagerService.getClass();
            Class<?> paramTypes1[] = getParamTypes(pmService, "deletePackageAsUser");
            method = pmService.getMethod("deletePackageAsUser", paramTypes1);
            method.invoke(PackageManagerService, packageName, null, getUserId(Binder.getCallingUid()), 0x00000040);//getUserId
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }
    }

    private static Class<?>[] getParamTypes(Class<?> cls, String mName) {
        Class<?> cs[] = null;
        Method[] mtd = cls.getMethods();
        for (int i = 0; i < mtd.length; i++) {
            if (!mtd[i].getName().equals(mName)) {
                continue;
            }

            cs = mtd[i].getParameterTypes();
        }
        return cs;
    }

    public static final int PER_USER_RANGE = 100000;

    public static int getUserId(int uid) {
        return uid / PER_USER_RANGE;
    }

    private static List<AppDownloadInfo> taskList = new ArrayList<>();
    public static List<DownloadInfo> alltask;

    static String packageName = "";

    public static void setInstallIngPackageName(String packageNames) {
        packageName = packageNames;
        Log.e("fht", "正在安装：" + packageNames);
    }

    public static String getinstallPackage() {
        return packageName;
    }

    public static boolean isInstalling(String packageNames) {
        Log.e("fht", "isInstalling：" + packageName);
        return packageName.equals(packageNames);
    }

    public static DownloadInfo getDownloadInfoByPackageName(String s) {
        int x = -1;
        if (alltask != null && alltask.size() > 0) {
            for (int i = 0; i < alltask.size(); i++) {
                DownloadInfo downloadInfo = alltask.get(i);
                AppDateInfo dateInfo = (AppDateInfo) downloadInfo.getData();
                if (dateInfo.getApp_baoming().equals(s)) {
                    x = i;
                }
            }
        }
        if (x != -1) {
            return alltask.get(x);
        } else {
            return null;
        }
    }

    static synchronized public void updateTask(List<DownloadInfo> allTask, Context context) {
        alltask = allTask;
        Log.e("fht", "updateTask：" + allTask.size());
        long time1 = System.currentTimeMillis();
        List<AppDownloadInfo> list = new ArrayList<>();
        if (allTask.size() > 0) {
            for (int i = 0; i < allTask.size(); i++) {
                DownloadInfo downloadInfo = allTask.get(i);
                if (downloadInfo != null && StorageUtils.isFileIsExists(downloadInfo.getTargetPath())) {
                    AppDateInfo dateInfo = (AppDateInfo) downloadInfo.getData();
                    if (!dateInfo.getApp_baoming().equals(Utils.YOUNGSYSTEM_APP_TONGBU) && !dateInfo.getApp_baoming().equals(context.getPackageName())) {
                        AppDownloadInfo info = new AppDownloadInfo();
                        info.setFileName(downloadInfo.getFileName());
                        info.setProgress(downloadInfo.getProgress());
                        info.setTargetPath(downloadInfo.getTargetPath());
                        info.setUrl(downloadInfo.getUrl());
                        info.setState(downloadInfo.getState());
                        info.setDownloadLength(downloadInfo.getDownloadLength());
                        info.setTotalLength(downloadInfo.getTotalLength());
                        info.setPackageName(dateInfo.getApp_baoming());
                        info.setVersion(dateInfo.getApp_banben());
                        info.setData(dateInfo);
                        list.add(info);
                    }
                }
            }
        }
        long time2 = System.currentTimeMillis();
        Log.e("fht", "time:" + (time2 - time1));
        taskList = list;
        if ((packageName.equals("") || isAvailable(context, getinstallPackage())) && taskList.size() > 0 && taskList.get(0).getState() == DownloadManager.FINISH) {
            if (isAvailable(context, taskList.get(0).getPackageName())) {
                taskList.remove(0);
            }
            if (taskList.size() > 0) {
                ApkUtils.installApkInSilence(taskList.get(0).getTargetPath(), taskList.get(0).getPackageName());
                Log.e("fht", "updateTask1:" + taskList.get(0).getPackageName());
            }
        }
    }


    synchronized public static void removeInfo(String packageName) {
        Log.e("fht", "removeInfo:" + "taskList.size():" + taskList.size());

        int position = -1;
        for (int i = 0; i < taskList.size(); i++) {
            if (packageName.equals(taskList.get(i).getPackageName())) {
                position = i;
            }
        }
        if (position != -1) {
            removeInfo(taskList.get(position));
        } else {
            setInstallIngPackageName("");
            Log.e("fht", "position == -1");
        }
    }

    synchronized public static void removeInfo(AppDownloadInfo info) {
        taskList.remove(info);
        if (taskList != null && taskList.size() > 0) {
            ApkUtils.installApkInSilence(taskList.get(0).getTargetPath(), taskList.get(0).getPackageName());
            Log.e("fht", "removeInfo:" + taskList.get(0).getPackageName());
        } else {
            setInstallIngPackageName("");
            Log.e("fht", "任务为空");
        }
    }

}
