package cn.tee3.manager.service;

import android.Manifest;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.Context;
import android.content.pm.PackageManager;
import android.util.Log;
import com.tbruyelle.rxpermissions2.Permission;
import com.tbruyelle.rxpermissions2.RxPermissions;
import java.util.ArrayList;
import java.util.List;
import androidx.core.content.ContextCompat;
import cn.tee3.avd.Tlog;
import cn.tee3.manager.bean.RxBusMsgObj;
import cn.tee3.manager.util.RxBus;
import io.reactivex.disposables.Disposable;
import io.reactivex.functions.Consumer;

/**
 * 动态权限获取
 */
public class RequestPermissions {
    private static RxPermissions rxPermissions;
    private static Disposable disposable;
    private static Activity activity;
    private static int permissionNum;
    private static Helper helper;

    private static PermissionCode isGranted = PermissionCode.REFUSE;
    private static List<String> permissionList;

    public enum PermissionCode {
        GRANTED,
        REFUSE,
        NO_LONGER_ASK
    }

    private RequestPermissions() {
    }

    public static RequestPermissions getInstance() {
        return Builder.INSTANCE;
    }

    public static Helper permissionHelper(Activity activity) {
        if (permissionList == null) {
            permissionList = new ArrayList<>();
            permissionList.add(Manifest.permission.CAMERA);
            permissionList.add(Manifest.permission.RECORD_AUDIO);
            permissionList.add(Manifest.permission.READ_EXTERNAL_STORAGE);
            permissionList.add(Manifest.permission.WRITE_EXTERNAL_STORAGE);
            permissionList.add(Manifest.permission.READ_PHONE_STATE);
        }
        if (RequestPermissions.activity != activity) {
            RequestPermissions.activity = activity;
            rxPermissions = new RxPermissions(activity);
        }
        helper = new Helper();
        return helper;
    }

    private static class Builder {
        private static final RequestPermissions INSTANCE = new RequestPermissions();
    }

    public void dispose() {
        activity = null;
        callback = null;
        rxPermissions = null;
        helper = null;
        permissionNum = 0;
        isGranted = PermissionCode.REFUSE;
        if (disposable != null) {
            disposable.dispose();
        }
        LogHelper.getInstance().appendLog("┣   cn.tee3.manager.service :: RequestPermissions.dispose()").printLog();
    }

    public PermissionCode isGranted() {
        return isGranted;
    }

    public static class Helper {
        private RxPermissions objCheck() {
            if (rxPermissions == null && activity != null) {
                rxPermissions = new RxPermissions(activity);
            }
            return rxPermissions;
        }

        private void check() {
            permissionNum++;
            if (permissionNum == permissionList.size()) {
                permissionNum = 0;
                if (isGranted == PermissionCode.GRANTED) {
                    RxBus.getInstance().post(new RxBusMsgObj(RxBusMsgObj.MsgTag.Permission, PermissionCode.GRANTED));
                } else {
                    RxBus.getInstance().post(new RxBusMsgObj(RxBusMsgObj.MsgTag.Permission, PermissionCode.REFUSE));
                }
            }
        }

        public void requestAll() {
            permissionNum = 0;
            LogHelper.getInstance().appendLog("┃\n┃\t┣  cn.tee3.manager.service :: RequestPermissions.init()").printLog();
            if (isGranted == PermissionCode.GRANTED) {
                RxBus.getInstance().post(new RxBusMsgObj(RxBusMsgObj.MsgTag.Permission, PermissionCode.GRANTED));
            } else {
                for (String code : permissionList) {
                    request(code, new PermissionRequestCallback() {
                        @Override
                        public void onRequestCallback(Permission permission) {
                        }

                        @Override
                        public void onGranted(String code) {
                            check();
                        }

                        @Override
                        public void onRefused(String code) {
                            isGranted = PermissionCode.REFUSE;
                            check();
                        }

                        @Override
                        public void onNoLongerAsk(String code) {
                            isGranted = PermissionCode.NO_LONGER_ASK;
                            check();
                        }
                    });
                }
            }
        }

        @SuppressLint("CheckResult")
        public void request(final String permissions, PermissionRequestCallback callback) {
            disposable = objCheck().requestEach(permissions)
                    .subscribe(new Consumer<Permission>() {
                        @Override
                        public void accept(Permission permission) {
                            if (permission.granted) {
                                if (isGranted(permissionList)) {
                                    isGranted = PermissionCode.GRANTED;
                                }
                                if (permission.name.equals(Manifest.permission.WRITE_EXTERNAL_STORAGE)) {
                                    RxBus.getInstance().post(new RxBusMsgObj(RxBusMsgObj.MsgTag.Permission_Write_External_Storage));
                                }
                            }
                            if (callback != null) {
                                callback.onRequestCallback(permission);
                                if (permission.granted) {
                                    Tlog.d("RequestPermissions", permission.name + " ->  granted");
                                    callback.onGranted(permission.name);
                                } else if (permission.shouldShowRequestPermissionRationale) {
                                    Tlog.d("RequestPermissions", permission.name + " ->  refused");
                                    callback.onRefused(permission.name);
                                } else {
                                    Tlog.d("RequestPermissions", permission.name + " ->  noLongerAsk");
                                    callback.onNoLongerAsk(permission.name);
                                }
                            }
                        }
                    });
        }

        @SuppressLint("CheckResult")
        public void request(PermissionRequestCallback callback, final String... permissions) {
            for (String code : permissions) {
                request(code, callback);
            }
        }

        public boolean isGranted(String permission) {
            objCheck();
            return rxPermissions.isGranted(permission);
        }

        public boolean isGranted(List<String> permissionList) {
            objCheck();
            for (String permission : permissionList) {
                boolean granted = rxPermissions.isGranted(permission);
                if (!granted) {
                    return false;
                }
            }
            return true;
        }
    }

    public boolean isGranted(Context context, String permission) {
        return ContextCompat.checkSelfPermission(context, permission) == PackageManager.PERMISSION_GRANTED;
    }

    private static PermissionRequestCallback callback;

    public interface PermissionRequestCallback {
        void onRequestCallback(Permission permission);

        void onGranted(String code);

        void onRefused(String code);

        void onNoLongerAsk(String code);
    }

    public interface PermissionRequestTotalCallback {
        void onRequest(boolean isGranted);
    }
}
