package com.uiui.zyappstore.utils;

import android.annotation.SuppressLint;
import android.content.ComponentName;
import android.content.Context;
import android.content.ContextWrapper;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.os.BatteryManager;
import android.os.Build;
import android.os.Environment;
import android.os.PowerManager;
import android.provider.Settings;
import android.telephony.TelephonyManager;
import android.text.TextUtils;
import android.util.Log;

import androidx.core.content.ContextCompat;

import com.blankj.utilcode.util.FileUtils;
import com.uiui.zyappstore.BuildConfig;
import com.uiui.zyappstore.receiver.BootReceiver;

import java.io.File;
import java.io.IOException;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.nio.file.Files;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.function.BiConsumer;

import io.reactivex.rxjava3.annotations.NonNull;
import io.reactivex.rxjava3.core.Observable;
import io.reactivex.rxjava3.core.ObservableEmitter;
import io.reactivex.rxjava3.core.ObservableOnSubscribe;
import io.reactivex.rxjava3.core.Observer;
import io.reactivex.rxjava3.disposables.Disposable;


public class JGYUtils {
    private static final String TAG = JGYUtils.class.getSimpleName();

    private static JGYUtils sInstance;
    private Context mContext;

    public static final int MTKPlatform = 1;
    public static final int CubePlatform = 2;
    public static final int ZhanruiPlatform = 3;
    public static final int UMTK11Platform = 4;
    public static final int UZY12Platform = 7;
    public static final int Cube8183Platform = 8;
    public static final int Teclast8183Platform = 9;
    public static final int ipaly50SEPlatform = 10;
    public static final int UnknowPlatform = 0;

    public static final String MTKTag = "MTK";
    public static final String ZhanruiTag = "展锐";//酷比展睿
    public static final String NewZhanruiTag = "新展锐";
    public static final String UMTK11Tag = "UMTK11";
    public static final String UZY12Tag = "UZY12";
    public static final String Cube8183Tag = "cube8183";
    public static final String TeclastMTK12Tag = "teclast8183";
    public static final String ipaly50SETag = "ipaly50SE";


    private JGYUtils(Context context) {
        this.mContext = context;
    }

    public static void init(Context context) {
        if (sInstance == null) {
            sInstance = new JGYUtils(context);
        }
    }

    public static JGYUtils getInstance() {
        if (sInstance == null) {
            throw new IllegalStateException("You must be init JGYUtils first");
        }
        return sInstance;
    }

    public String getDownLoadPath() {
        String path = ContextCompat.getExternalFilesDirs(mContext, Environment.DIRECTORY_DOWNLOADS)[0].getAbsolutePath();
        return path + File.separator;
    }

    public static boolean isOfficialVersion() {
        String channelValue = JGYUtils.getInstance().getStringMetaData();
        return "official".equals(channelValue);
    }

    public static boolean isNewlyVersion() {
        String channelValue = JGYUtils.getInstance().getStringMetaData();
        return "beta".equals(channelValue);
    }

    public static boolean isBetaVersion() {
        String channelValue = JGYUtils.getInstance().getStringMetaData();
        return "beta".equals(channelValue);
    }


    private int getBatteryLevel() {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            BatteryManager batteryManager = (BatteryManager) mContext.getSystemService(Context.BATTERY_SERVICE);
            return batteryManager.getIntProperty(BatteryManager.BATTERY_PROPERTY_CAPACITY);
        } else {
            Intent intent = new ContextWrapper(mContext).registerReceiver(null, new IntentFilter(Intent.ACTION_BATTERY_CHANGED));
            return (intent.getIntExtra(BatteryManager.EXTRA_LEVEL, -1) * 100) /
                    intent.getIntExtra(BatteryManager.EXTRA_SCALE, -1);
        }
    }


    private PowerManager.WakeLock wakeLock = null;
    private static final String mWakeLockName = "BackupService";

    /**
     * 获取电源锁，保持该服务在屏幕熄灭时仍然获取CPU时，保持运行
     */
    @SuppressLint("InvalidWakeLockTag")
    private synchronized void acquireWakeLock() {
        if (null == wakeLock) {
            PowerManager pm = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
            wakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK
                    | PowerManager.ON_AFTER_RELEASE, mWakeLockName);
            if (null != wakeLock) {
                Log.e("fht", "acquireWakeLock!");
                wakeLock.acquire();
            }
        }
    }

    /**
     * 释放设备电源锁
     */
    private synchronized void releaseWakeLock() {
        if (null != wakeLock) {
            Log.e("fht", "releaseWakeLock!");
            wakeLock.release();
            wakeLock = null;
        }
    }


    /**
     * @param ids      需要管控的ID
     * @param packages 应用程序包名
     */
    public void writeDeselectIDtoSystem(String ids, String packages) {
        if (!TextUtils.isEmpty(ids) && !TextUtils.isEmpty(packages)) {
            ArrayList<String> idArrayList = new ArrayList<>(Arrays.asList(ids.split(",")));
            ArrayList<String> packageArrayList = new ArrayList<>(Arrays.asList(packages.split(",")));
            LinkedHashSet<String> idHashSet = new LinkedHashSet<>(idArrayList);
            LinkedHashSet<String> packageHashSet = new LinkedHashSet<>(packageArrayList);
            ArrayList<String> idList = new ArrayList<>(idHashSet);
            ArrayList<String> packageList = new ArrayList<>(packageHashSet);
            StringBuilder idStringBuilder = new StringBuilder();
            for (String id : idList) {
                if (idStringBuilder.length() > 0) {
                    idStringBuilder.append(",");
                }
                idStringBuilder.append(id);
            }
            StringBuilder packageStringBuilder = new StringBuilder();
            for (String pkg : packageList) {
                if (packageStringBuilder.length() > 0) {
                    packageStringBuilder.append(",");
                }
                packageStringBuilder.append(pkg);
            }


            String olddeselectViewArray = Settings.System.getString(mContext.getContentResolver(), "aole_app_forbid_id");
            Log.e("writeDeselectIDtoSystem", "olddeselectViewArray: " + olddeselectViewArray);

            Settings.System.putString(mContext.getContentResolver(), "aole_app_forbid_id", packageStringBuilder.toString());
            Settings.System.putString(mContext.getContentResolver(), "DeselectViewArray", idStringBuilder.toString());
            Log.e("writeDeselectIDtoSystem", "aole_app_forbid_id: " + packageStringBuilder.toString());
            Log.e("writeDeselectIDtoSystem", "deselectViewArray: " + idStringBuilder.toString());
        } else {
            Log.e("writeDeselectIDtoSystem", "writeDeselectIDtoSystem is null:");
            Settings.System.putString(mContext.getContentResolver(), "aole_app_forbid_id", "");
            Settings.System.putString(mContext.getContentResolver(), "DeselectViewArray", "");
        }
    }


    private static void sendAllweb(Context context) {
        Intent intent = new Intent("qch_app_website")
                .setPackage("com.android.settings");
        intent.putExtra("package_name", "Invalid");
        context.sendBroadcast(intent);
    }

    private static void sendwebUrl(Context context) {
        Intent intent = new Intent("qch_app_inside_website")
                .setPackage("com.android.settings");
        intent.putExtra("websitelist", "Invalid");
        context.sendBroadcast(intent);
    }


    /**
     * 从Manifest中获取meta-data值
     * https://blog.csdn.net/yue_233/article/details/91453451
     *
     * @return
     */
    public String getStringMetaData() {
        ApplicationInfo appInfo = null;
        try {
            appInfo = mContext.getPackageManager().getApplicationInfo(mContext.getPackageName(), PackageManager.GET_META_DATA);
        } catch (PackageManager.NameNotFoundException e) {
            e.printStackTrace();
        }
        String value = appInfo.metaData.getString("CHANNEL_VALUE");
        return value;
    }

    public static void hookWebView() {
        int sdkInt = Build.VERSION.SDK_INT;
        try {
            Class<?> factoryClass = Class.forName("android.webkit.WebViewFactory");
            Field field = factoryClass.getDeclaredField("sProviderInstance");
            field.setAccessible(true);
            Object sProviderInstance = field.get(null);
            if (sProviderInstance != null) {
                Log.i(TAG, "sProviderInstance isn't null");
                return;
            }

            Method getProviderClassMethod;
            if (sdkInt > 22) {
                getProviderClassMethod = factoryClass.getDeclaredMethod("getProviderClass");
            } else if (sdkInt == 22) {
                getProviderClassMethod = factoryClass.getDeclaredMethod("getFactoryClass");
            } else {
                Log.i(TAG, "Don't need to Hook WebView");
                return;
            }
            getProviderClassMethod.setAccessible(true);
            Class<?> factoryProviderClass = (Class<?>) getProviderClassMethod.invoke(factoryClass);
            Class<?> delegateClass = Class.forName("android.webkit.WebViewDelegate");
            Constructor<?> delegateConstructor = delegateClass.getDeclaredConstructor();
            delegateConstructor.setAccessible(true);
            if (sdkInt < 26) {//低于Android O版本
                Constructor<?> providerConstructor = factoryProviderClass.getConstructor(delegateClass);
                if (providerConstructor != null) {
                    providerConstructor.setAccessible(true);
                    sProviderInstance = providerConstructor.newInstance(delegateConstructor.newInstance());
                }
            } else {
                Field chromiumMethodName = factoryClass.getDeclaredField("CHROMIUM_WEBVIEW_FACTORY_METHOD");
                chromiumMethodName.setAccessible(true);
                String chromiumMethodNameStr = (String) chromiumMethodName.get(null);
                if (chromiumMethodNameStr == null) {
                    chromiumMethodNameStr = "create";
                }
                Method staticFactory = factoryProviderClass.getMethod(chromiumMethodNameStr, delegateClass);
                if (staticFactory != null) {
                    sProviderInstance = staticFactory.invoke(null, delegateConstructor.newInstance());
                }
            }

            if (sProviderInstance != null) {
                field.set("sProviderInstance", sProviderInstance);
                Log.i(TAG, "Hook success!");
            } else {
                Log.i(TAG, "Hook failed!");
            }
        } catch (Throwable e) {
            Log.w(TAG, e);
        }
    }


    /**
     * 忽略电池优化
     */
    private void ignoreBatteryOptimization(Context context) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {

            PowerManager powerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);

            boolean hasIgnored = powerManager.isIgnoringBatteryOptimizations(context.getPackageName());
            //  判断当前APP是否有加入电池优化的白名单，如果没有，弹出加入电池优化的白名单的设置对话框。
            if (!hasIgnored) {
                Intent intent = new Intent(Settings.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS);
                intent.setData(Uri.parse("package:" + context.getPackageName()));
                intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                mContext.startActivity(intent);
            }
        }
    }


    public int checkSNPlatform(String sn) {
        String secondChars = sn.substring(1, 2);
        if ("N".equalsIgnoreCase(secondChars)) {//MTK平台
            return MTKPlatform;
        } else if ("R".equalsIgnoreCase(secondChars)) {//展锐平台
            return ZhanruiPlatform;
        } else {
            Log.e(TAG, "checkSNPlatform: " + "sn: " + sn + "没有对应平台");
            return UnknowPlatform;
        }
    }

    public int checkAppPlatform() {
        String platform = BuildConfig.platform;
        if (MTKTag.equalsIgnoreCase(platform)) {
            Log.i(TAG, "checkAppPlatform: " + "MTK平台");
            return MTKPlatform;
        } else if (ZhanruiTag.equalsIgnoreCase(platform)) {
            Log.i(TAG, "checkAppPlatform: " + "展锐平台");
            return CubePlatform;
        } else if (NewZhanruiTag.equalsIgnoreCase(platform)) {
            Log.i(TAG, "checkAppPlatform: " + "新展锐平台");
            return ZhanruiPlatform;
        } else if (UMTK11Tag.equalsIgnoreCase(platform)) {
            Log.i(TAG, "checkAppPlatform: " + "UMTK11");
            return UMTK11Platform;
        } else if (UZY12Tag.equalsIgnoreCase(platform)) {
            Log.i(TAG, "checkAppPlatform: " + "UZY12");
            return UZY12Platform;
        }else if (Cube8183Tag.equalsIgnoreCase(platform)) {
            Log.i(TAG, "checkAppPlatform: " + "cube8183");
            return Cube8183Platform;
        } else if (TeclastMTK12Tag.equalsIgnoreCase(platform)) {
            Log.i(TAG, "checkAppPlatform: " + "teclast8183");
            return Teclast8183Platform;
        }else if (ipaly50SETag.equalsIgnoreCase(platform)) {
            Log.i(TAG, "checkAppPlatform: " + "ipaly50SE");
            return ipaly50SEPlatform;
        } else {
            Log.i(TAG, "checkAppPlatform: " + "没有数据");
            return UnknowPlatform;
        }
    }

    public boolean isSamePlatform(String platform) {
        String AppPlatform = BuildConfig.platform;
        if ("ZhanRui".equals(AppPlatform)) {
            return ZhanruiTag.equals(platform);
        } else {
            return AppPlatform.equals(platform);
        }
    }

    public interface GetAppPlatformCallback {
        void AppPlatform(int platform);
    }

    public void getAppPlatform(GetAppPlatformCallback getAppPlatformCallback) {
        String platform = BuildConfig.platform;
        if (MTKTag.equalsIgnoreCase(platform)) {
            getAppPlatformCallback.AppPlatform(MTKPlatform);
        } else if (ZhanruiTag.equalsIgnoreCase(platform)) {
            getAppPlatformCallback.AppPlatform(CubePlatform);
        } else if (NewZhanruiTag.equalsIgnoreCase(platform)) {
            getAppPlatformCallback.AppPlatform(ZhanruiPlatform);
        } else if (UMTK11Tag.equalsIgnoreCase(platform)) {
            getAppPlatformCallback.AppPlatform(UMTK11Platform);
        } else if (UZY12Tag.equalsIgnoreCase(platform)) {
            getAppPlatformCallback.AppPlatform(UZY12Platform);
        } else if (TeclastMTK12Tag.equalsIgnoreCase(platform)) {
            getAppPlatformCallback.AppPlatform(Teclast8183Platform);
        } else if (Cube8183Tag.equalsIgnoreCase(platform)) {
            getAppPlatformCallback.AppPlatform(Cube8183Platform);
        } else if (ipaly50SETag.equalsIgnoreCase(platform)) {
            getAppPlatformCallback.AppPlatform(ipaly50SEPlatform);
        } else {
            getAppPlatformCallback.AppPlatform(UnknowPlatform);
        }
    }

    public static final String PACKAGE_DEVICEINFO = "com.uiui.sn";
    public static final String PACKAGE_APPSTORE = "com.uiui.zyappstore";
    public static final String PACKAGE_UPDATETOOLS = "com.uiui.updatetools";
    public static final String CLASS_DEVICEINFO = "com.uiui.sn.receiver.BootReceiver";
    public static final String CLASS_APPSTORE = "com.uiui.zyappstore.receiver.BootReceiver";
    public static final String CLASS_UPDATETOOLS = "com.uiui.updatetools.receiver.BootReceiver";

    public void wakeUpDeviceInfo() {
        //启动设备信息
        Intent bootIntent = new Intent(BootReceiver.BOOT_COMPLETED);
        bootIntent.setComponent(new ComponentName(PACKAGE_DEVICEINFO, CLASS_DEVICEINFO));
        mContext.sendBroadcast(bootIntent);
    }

    public void wakeUpAppstore() {
        //启动应用市场
        Intent bootIntent = new Intent(BootReceiver.BOOT_COMPLETED);
        bootIntent.setComponent(new ComponentName(PACKAGE_APPSTORE, CLASS_APPSTORE));
        mContext.sendBroadcast(bootIntent);
    }

    public void wakeUpUpdateTools() {
        //启动升级组件
        Intent bootIntent = new Intent(BootReceiver.BOOT_COMPLETED);
        bootIntent.setComponent(new ComponentName(PACKAGE_UPDATETOOLS, CLASS_UPDATETOOLS));
        mContext.sendBroadcast(bootIntent);
    }

    public  String getIMEI() {
        String IMEI = "unknow";
        String IMEI1, IMEI2, IMEI3;
        //获取手机设备号
        TelephonyManager TelephonyMgr = (TelephonyManager) mContext.getSystemService(Context.TELEPHONY_SERVICE);
        //8.0及以后版本获取
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            IMEI = TelephonyMgr.getDeviceId();
        } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
//            try {
//                Method method = TelephonyMgr.getClass().getMethod("getImei");
//                IMEI = (String) method.invoke(TelephonyMgr);
//            } catch (Exception e) {
//                e.printStackTrace();
//                Log.e("getIMEI", e.getMessage());
//            }
//            IMEI = TelephonyMgr.getDeviceId();

//        } else {//9.0到10.0获取
            IMEI = Settings.System.getString(mContext.getContentResolver(), Settings.Secure.ANDROID_ID);
        }
//        Log.e("IMEI:", "IMEI: " + IMEI);
        if (null == IMEI) {
            return "-";
        } else {
            return IMEI.toUpperCase();
        }
    }

    public String getPushMac() {
        String macaddr = Utils.getAndroid10MAC(mContext);
        return macaddr.replace(":", "");
    }

    public boolean isScreenOn() {
        PowerManager powerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
        //true为打开，false为关闭
        return powerManager.isInteractive();
    }

    public List<String> externalPkg = new ArrayList<String>() {{
        this.add("com.aoleyun.appstore");
        this.add("com.aoleyun.browser");
        this.add("com.aoleyun.sn");
        this.add("com.aoleyun.info");

        this.add("com.qi.studycomputer.launcher");
        this.add("com.wyt.evaluating");
        this.add("com.qi.childsystem.launcher");
        this.add("com.qi.TFSystem");
        this.add("com.yixuetong.user");
        this.add("com.wyt.tongbuyouxue");
        this.add("air.wyt.modloader");

        this.add("com.alibaba.android.rimet");
        this.add("com.tencent.wemeet.app");
    }};

    private static final String AOLE_DIR = "aole";
    public HashMap<String, String> mPackageListMap = new HashMap<>();

    public void checkLocalExternalFiles() {
        File[] externalFiles = mContext.getExternalFilesDirs(null);
        Log.e(TAG, "checkLocalAppInstall: externalFiles = " + Arrays.toString(externalFiles));

        String SdPath = Environment.getExternalStorageDirectory().getAbsolutePath();
        Log.e(TAG, "checkLocalAppInstall: SdPath = " + SdPath);
        String aolePath = SdPath + File.separator + AOLE_DIR;
        File file = new File(aolePath);
        String[] apkName = file.list();
        if (apkName == null || apkName.length == 0) {
            Log.e(TAG, "checkLocalAppInstall: apkName is empty");
        } else {
            Observable.create(new ObservableOnSubscribe<HashMap<String, String>>() {
                @Override
                public void subscribe(@NonNull ObservableEmitter<HashMap<String, String>> emitter) throws Throwable {
                    HashMap<String, String> packageListMap = new HashMap<>();
                    for (String fileName : apkName) {
                        String apkPath = aolePath + File.separator + fileName;
                        Log.e(TAG, "subscribe: " + apkPath);
                        String pkg = ApkUtils.getPackageName(mContext, apkPath);
//                        if (externalPkg.contains(pkg)) {
                            packageListMap.put(pkg, apkPath);
//                        } else {
//                            Log.e(TAG, "checkLocalAppInstall: skip: " + pkg + " fileName: " + fileName);
//                        }
                    }
                    mPackageListMap = packageListMap;
                    emitter.onNext(packageListMap);
                }
            }).subscribe(new Observer<HashMap<String, String>>() {
                @Override
                public void onSubscribe(@NonNull Disposable d) {
                    Log.e("checkLocalAppInstall", "onSubscribe: ");
                }

                @Override
                public void onNext(@NonNull HashMap<String, String> stringStringHashMap) {
                    Log.e("checkLocalAppInstall", "onNext: " + stringStringHashMap);
                    stringStringHashMap.forEach(new BiConsumer<String, String>() {
                        @Override
                        public void accept(String key, String value) {
                            if (ApkUtils.isAvailable(mContext, key)) {
                                Log.e("checkLocalAppInstall", "accept: installed: " + key);
                            } else {
//                                copyFile(value);
                                ApkUtils.installApp(mContext, value);
                            }
                        }
                    });
                }

                @Override
                public void onError(@NonNull Throwable e) {
                    Log.e("checkLocalAppInstall", "onError: " + e.getMessage());
                    onComplete();
                }

                @Override
                public void onComplete() {
                    Log.e("checkLocalAppInstall", "onComplete: ");

                }
            });
        }
    }

    private void copyFile(String filePath) {
        Log.e(TAG, "copyFile: " + filePath);
        File file = new File(filePath);
        String fileName = file.getName();
        String newFilePath = getDownLoadPath() + fileName;
        File newFile = new File(newFilePath);
        String fileMD5 = com.blankj.utilcode.util.FileUtils.getFileMD5ToString(file);
        String newFileMD5 = FileUtils.getFileMD5ToString(newFile);
        if (newFile.exists()) {
            if (fileMD5.equals(newFileMD5)) {
//                AdminManager.getInstance().installPackage(newFilePath);
            } else {
                newFile.delete();
                try {
                    Files.copy(file.toPath(), newFile.toPath());
//                    AdminManager.getInstance().installPackage(newFilePath);
                } catch (IOException e) {
                    e.printStackTrace();
                    Log.e("Files.copy", "IOException:" + e.getMessage());
                }
            }
        } else {
            try {
                Files.copy(file.toPath(), newFile.toPath());
//                AdminManager.getInstance().installPackage(newFilePath);
            } catch (IOException e) {
                e.printStackTrace();
                Log.e("Files.copy", "IOException:" + e.getMessage());
            }
        }
    }
}
