package cgmblelib.ble.scancallback;

import android.annotation.SuppressLint;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.os.Build;

import androidx.annotation.NonNull;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;

import cgmblelib.ble.BleService;
import cgmblelib.ble.gattcallback.BleGattCallback;
import cgmblelib.ble.gattcallback.ManageGattCallback;
import cgmblelib.ble.reconnectManagament.ReconnectManagement;
import cgmblelib.custom.livedata.ManagementLiveData;
import cgmblelib.custom.livedata.scan.EnumScan;
import cgmblelib.database.entity.PocDevice;
import cgmblelib.utils.ConstantsLibrary;
import cgmblelib.utils.MyLog;
import cgmblelib.utils.PermissionCheckTool;
import cgmblelib.utils.Tool;
import io.reactivex.Observable;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.disposables.Disposable;
import ist.com.sdk.ProtocolTools;

/**
 * 搜索控制类
 * Created by minyuchun on 2019/12/23.
 *
 * @author minyuchun
 */
public class ManageScanCallback {
    /**
     * 默认的搜索时长
     */
    private final static int SCAN_INTERVAL_DEFAULT = 6 * 1000;
    /**
     * RXJava 订阅
     */
    private Disposable mDisposable;

    public ManageScanCallback() {
    }

    private static class SingletonInstance {
        private static final ManageScanCallback INSTANCE = new ManageScanCallback();
    }

    public static ManageScanCallback getInstance() {
        return SingletonInstance.INSTANCE;
    }

    /**
     * 服务
     */
    private BleService mService;
    /**
     * 协议
     */
    private ProtocolTools mProtocolTools;
    /**
     * 搜索到的设备
     */
    private List<BluetoothDevice> mScanLeDeviceList = new ArrayList<>();
    /**
     * 在API版本21以及之后的搜索类
     */
    private BleScanCallback mScanCallback;
    /**
     * 权限查看框架
     */
    private PermissionCheckTool mPermissionCheckTool;
    /**
     * 正在搜索设备的标志位
     */
    private boolean isScanning = true;
    /**
     * 需要连接的设备
     */
    private PocDevice mPocDevice;

    private BluetoothAdapter adapter;

    /**
     * 初始化数据
     *
     * @param service 服务
     */
    public void init(@NonNull BleService service) {
        mService = service;
        mPermissionCheckTool = new PermissionCheckTool(service);
        mScanCallback = new BleScanCallback();
        mProtocolTools = new ProtocolTools();
    }

    /**
     * 进行搜索重连
     * 1.先停止搜索
     * 2.设置需要重连的发射器
     * 3.开始搜索->重连
     *
     * @param device 重连时候设置发射器信息
     */
    public void reConnectViaScan(PocDevice device) {
        if (mService == null) {
            MyLog.iLog("scan mService is null");
            return;
        }
        if (adapter == null) {
            adapter = Tool.getBluetoothAdapter(mService);
        }
        //首先停止以存在的搜索
        stopLeScan();
        //其次设置搜索需要的设备
        mPocDevice = device;
        //最后开始搜索
        startScan();
    }

    /**
     * 开始搜索蓝牙设备
     */
    public void startScan() {
        MyLog.d("startScan");
        if (isScanning) {
            return;
        }
        try {
            mScanLeDeviceList.clear();
            if (adapter != null && adapter.isEnabled()) {
                if (isBLEPermissionLocks()) {
                    //没有GPS的权限
                    MyLog.i("未获取本地权限");
                    ManagementLiveData.getInstance().updateOperationScan(EnumScan.SCAN_ERROR_LOCAL_OFF);
                } else if (!Tool.isGPSEnable_S(mService)) {
                    //没有开启GPS服务
                    MyLog.i("未开启GPS");
                    ManagementLiveData.getInstance().updateOperationScan(EnumScan.SCAN_ERROR_GPS_OFF);
                } else {
                    //开始启动蓝牙搜索
                    isScanning = mScanCallback.startScan(adapter);
                }
            } else {
                ManagementLiveData.getInstance().updateOperationScan(EnumScan.SCAN_ERROR_BLUETOOTH_OFF);
                ReconnectManagement.getInstance().stopReconnect();
            }
        } catch (Exception e) {
            e.printStackTrace();
            isScanning = false;
        } finally {
            if (isScanning) {
                if (mPocDevice != null) {
                    BleGattCallback.getInstance().closeGatt();
                }
                ManagementLiveData.getInstance().updateOperationScan(EnumScan.SCAN_START);
                stopScanDelay();
            } else {
                isScanning = true;
                stopLeScan();
            }
        }
    }

    /**
     * 停止搜索蓝牙设备
     */
    public void stopLeScan() {
        stopLeScan(false);
    }

    /**
     * 停止搜索蓝牙设备
     *
     * @param isNextConnect 已经搜索到发射, 下一步 连接准备
     */
    public void stopLeScan(boolean isNextConnect) {
        MyLog.i("stopLeScan");
        if (!isScanning) {
            return;
        }
        try {
            disposable();
            isScanning = false;
            //关闭搜索
            mScanCallback.stopLeScan(adapter);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (!isScanning) {
                //搜索结束
                ManagementLiveData.getInstance().updateOperationScan(EnumScan.SCAN_END);
            }
            mPocDevice = null;
        }
    }

    /**
     * 蓝牙搜索后回调
     *
     * @param callbackType 回调类型
     * @param device       设备
     * @param scanRecord   蓝牙广播二进制数据
     * @param rssi         接收到的功率
     */
    @SuppressLint("MissingPermission")
    public synchronized void onScanResult(int callbackType, BluetoothDevice device, byte[] scanRecord, int rssi) {
        if (mService == null || !isScanning) {
            return;
        }
        //扫描重连部分
        if (mPocDevice != null && mPocDevice.isBoundButDisConnect()) {
            if (device != null && device.getAddress() != null && device.getName() != null) {
                ProtocolTools.Verify verify = mProtocolTools.verify(scanRecord);
                if (verify != null && verify.getName() != null) {
                    if (mPocDevice.getAddress().equals(device.getAddress())) {
                        //不管发射器开关是否重置了都去连接
                        stopLeScan(true);
                        MyLog.i("scan result");
                        ManageGattCallback.getInstance().ConnectViaAddress(device.getAddress());
                    }
                }
            }
        } else {
            //搜索扫描部分
            BluetoothDevice bluetoothDevice = removeSameScanDevice(device);
            if (bluetoothDevice != null) {
                ProtocolTools.Verify verify = mProtocolTools.verify(scanRecord);
                if (verify != null && verify.getName() != null && !verify.isBound()) {
                    PocDevice pocDevice = new PocDevice(verify, bluetoothDevice.getAddress());
                    MyLog.i(verify.toString());
                    ManagementLiveData.getInstance().updateOperationScan(pocDevice, rssi);
                }
            }
        }

    }


    /**
     * 搜索失败
     *
     * @param errorCode 搜索失败
     */
    public void onScanFailed(int errorCode) {
        MyLog.eLog("onScanFailed errorCode = " + errorCode);
        stopLeScan();
    }


    /**
     * 当系统蓝牙发生变化时, 搜索控制类的变化
     *
     * @param isBluetoothOpen 蓝牙是否开启
     */
    public void bluetoothChange(boolean isBluetoothOpen) {
        if (isBluetoothOpen) {
            ReconnectManagement.getInstance().reconnect(ReconnectManagement.ReconnectState.STATE_BLUETOOTH_ON);
        } else {
            stopLeScan();
        }
    }

    /**
     * 延时停止搜索
     */
    private void stopScanDelay() {
        mDisposable = Observable.timer(SCAN_INTERVAL_DEFAULT, TimeUnit.MILLISECONDS)
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(aLong -> stopLeScan(), throwable -> {

                });
    }

    /**
     * 取消订阅任务
     */
    private void disposable() {
        if (mDisposable != null && !mDisposable.isDisposed()) {
            mDisposable.isDisposed();
        }
    }

    /***
     * 查看是否被授予local权限
     * @return true：有权限未被授权
     */
    private boolean isBLEPermissionLocks() {
        if (mPermissionCheckTool != null) {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S){
                return mPermissionCheckTool.lacksPermissions(ConstantsLibrary.BLUETOOTH_S);
            }
            return mPermissionCheckTool.lacksPermissions(ConstantsLibrary.LOCAL_PERMISSION);
        }
        return false;
    }

    /**
     * 排除搜索到相同的设备
     *
     * @param device 蓝牙设备
     */
    @SuppressLint("MissingPermission")
    private synchronized BluetoothDevice removeSameScanDevice(BluetoothDevice device) {
        if (device != null && device.getName() != null && device.getAddress() != null) {
            if (!mScanLeDeviceList.contains(device)) {
                mScanLeDeviceList.add(device);
                return device;
            }
        }
        return null;
    }
}
