package com.cmcm.crashhandler;

import android.app.ActivityManager;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.os.Build;
import android.os.Debug;
import android.os.Environment;
import android.os.Process;
import android.os.StatFs;
import android.provider.Settings;
import android.text.TextUtils;

import com.cmcm.crashhandler.bridge.RNCrashHandlerModule;
import com.cmcm.crashhandler.bridge.ReactEnvironmentHelper;

import java.io.File;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

/***
 ** @author nieyihe
 ** @email nieyihe@cmcm.com
 ** @date 2019/4/22
 **/
public class DeviceUtils {

    /**
     * 获取Android ID
     * */
    public static String getAndroidId(Context context) {
        try {
            ContentResolver cr = context.getContentResolver();
            return Settings.System.getString(cr, android.provider.Settings.System.ANDROID_ID);
        } catch (Exception e) {
            return "";
        }
    }

    /**
     * 获取内存信息
     * */
    public static String getMemoryInfoString() {
        Debug.MemoryInfo meminfo = new Debug.MemoryInfo();
        Debug.getMemoryInfo(meminfo);
        StringBuffer sb = new StringBuffer(128);
        try {
            Class<?> clzMemoryInfo = meminfo.getClass();
            Field fidOtherStats = clzMemoryInfo.getDeclaredField("otherStats");
            fidOtherStats.setAccessible(true);
            int[] otherStats = (int[]) fidOtherStats.get(meminfo);
            if (otherStats != null && otherStats.length > 0) {
                for (int i = 0; i < otherStats.length; i++) {
                    sb.append(otherStats[i]);
                    if (i < otherStats.length - 1)
                        sb.append(',');
                }
            }
        } catch (Exception e) {
        }

        return meminfo.getTotalPss() + "/" + meminfo.dalvikPss + "/" + meminfo.nativePss + "/" + meminfo.otherPss + "/"
                + Runtime.getRuntime().maxMemory() + "/" + sb.toString();
    }

    /**
     * 获取?
     * */
    public static int getNativeFdCnt() {
        try {
            File x = new File("/proc/self/fd");
            if (x.exists()) {
                if (x.isDirectory())
                    return x.listFiles().length;
                else
                    return -2;
            }
        } catch (Exception e) {
            return -1;
        }
        return 0;
    }

    /**
     * 获取存储大小 单位bytes
     * */
    public static String getDeviceStorageInfo() {
        File storagePathFile = Environment.getDataDirectory();
        if (null == storagePathFile) {
            return null;
        }

        StatFs fsStat = null;

        try {
            fsStat = new StatFs(storagePathFile.getPath());
        } catch (Exception e) {
            return null;
        }

        long sdAvailableBlocks = getAvailableBlocks(fsStat);// 可用存储块的数量
        long sdBlockcount = getBlockCount(fsStat);// 总存储块的数量
        long sdSize = getBlockSize(fsStat);// 每块存储块的大小

        long allSize = sdBlockcount * sdSize;
        long freeSize = sdAvailableBlocks * sdSize;

        if (allSize < freeSize) {
            freeSize = allSize;
        }
        return freeSize + "/" + allSize;
    }

    private static long getAvailableBlocks(StatFs fsStat) {
        assert(null != fsStat);

        if (Build.VERSION.SDK_INT < 18) {
            return fsStat.getAvailableBlocks();
        }

        Method getAvailableBlocksLongMethod = null;
        try {
            getAvailableBlocksLongMethod = fsStat.getClass().getMethod("getAvailableBlocksLong");
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        }

        if (null == getAvailableBlocksLongMethod) {
            return fsStat.getAvailableBlocks();
        }

        try {
            return (Long)getAvailableBlocksLongMethod.invoke(fsStat);
        } catch (IllegalArgumentException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }

        return fsStat.getAvailableBlocks();
    }

    private static long getBlockCount(StatFs fsStat) {
        assert(null != fsStat);

        if (Build.VERSION.SDK_INT < 18) {
            return fsStat.getBlockCount();
        }

        Method getBlockCountLongMethod = null;
        try {
            getBlockCountLongMethod = fsStat.getClass().getMethod("getBlockCountLong");
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        }

        if (null == getBlockCountLongMethod) {
            return fsStat.getBlockCount();
        }

        try {
            return (Long)getBlockCountLongMethod.invoke(fsStat);
        } catch (IllegalArgumentException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }

        return fsStat.getBlockCount();
    }

    private static long getBlockSize(StatFs fsStat) {
        assert(null != fsStat);

        if (Build.VERSION.SDK_INT < 18) {
            return fsStat.getBlockSize();
        }

        Method getBlockSizeLongMethod = null;
        try {
            getBlockSizeLongMethod = fsStat.getClass().getMethod("getBlockSizeLong");
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        }

        if (null == getBlockSizeLongMethod) {
            return fsStat.getBlockSize();
        }

        try {
            return (Long)getBlockSizeLongMethod.invoke(fsStat);
        } catch (IllegalArgumentException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }

        return fsStat.getBlockSize();
    }

    /**
     * 默认的桌面
     * */
    public static String getCurrentLauncherName(Context context) {
        if (null == context) {
            return null;
        }

        PackageManager pm = context.getPackageManager();
        if (null == pm) {
            return null;
        }

        Intent intent = new Intent(Intent.ACTION_MAIN);
        intent.addCategory(Intent.CATEGORY_HOME);
        ResolveInfo resolveInfo = pm.resolveActivity(intent, PackageManager.MATCH_DEFAULT_ONLY);
        if (null == resolveInfo || null == resolveInfo.activityInfo || null == resolveInfo.activityInfo.packageName) {
            return null;
        }

        // /< 多个launcher的情况下，没有设置默认的launcher，那么获取到的数据为android，故过滤掉
        if (resolveInfo.activityInfo.packageName.equals("android")) {
            return "";
        }

        return resolveInfo.activityInfo.loadLabel(pm).toString();
    }

    /**
     * 是否Root权限
     * */
    public static boolean isRoot() {
        final String[] bin_dirs = {"/system/sbin/",
                "/system/xbin/", "/system/bin/"};
        String suPath = null;
        for (int i = 0; i < bin_dirs.length; i++) {
            try {
                String path = bin_dirs[i] + "su";
                if (new File(path).exists()) {
                    suPath = path;
                    break;
                }
            } catch (Exception e) {
                e.printStackTrace();
                continue;
            }
        }
        if (!TextUtils.isEmpty(suPath)) {
            File file = new File(suPath);
            return file.canExecute();
        } else {
            return false;
        }
    }

    /**
     * 获取当前的进程名字
     * */
    public static String getCurrentProcessName(Context context) {
        int pid = Process.myPid();
        ActivityManager mActivityManager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
        for (ActivityManager.RunningAppProcessInfo appProcess : mActivityManager
                .getRunningAppProcesses()) {
            if (appProcess.pid == pid) {
                return appProcess.processName;
            }
        }
        return "unknow";
    }

    /**
     * 获取角色的名字
     * */
    public static String getCharacterName() {
        return ReactEnvironmentHelper.getCurrentCharacterName();
    }

    /**
     * 获取场景的名字
     * */
    public static String getScenesName() {
        return ReactEnvironmentHelper.getCurrentScenesName();
    }

    /**
     * 获取系统属性
     * */
    public static String getSystemProperties(String key) {
        String ret;
        try {
            Method systemProperties_get = Class.forName("android.os.SystemProperties").getMethod("get", String.class);
            if ((ret = (String) systemProperties_get.invoke(null, key)) != null)
                return ret;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
        return null;
    }
}
