package com.common.bluetooth.service;

import android.annotation.SuppressLint;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothManager;
import android.content.Context;
import android.content.pm.PackageManager;
import android.os.Handler;
import android.os.HandlerThread;
import android.util.Log;

import com.common.bluetooth.BtConstants;
import com.common.bluetooth.interfaces.IBluetoothSearch;

import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 蓝牙操作管理类
 *
 * @author wangym
 * @since 2021-10-19
 */
public class BluetoothLeClient {
    @SuppressLint("StaticFieldLeak")
    private static volatile BluetoothLeClient mInstance;

    private final static String TAG = "BluetoothLeClient";
    private final Context mContext;
    private static Handler mBluetoothWorker;
    private BluetoothAdapter mBluetoothAdapter;
    private BluetoothManager mBluetoothManager;
    private IBluetoothSearch mBluetoothSearcher;

    private final Map<String, BluetoothLeConnector> mGattConnectorMap
            = new ConcurrentHashMap<>();

    private BluetoothLeClient(Context context) {
        mContext = context.getApplicationContext();

        HandlerThread thread = new HandlerThread("bluetooth client worker");
        thread.start();
        mBluetoothWorker = new Handler(thread.getLooper());
    }

    public static BluetoothLeClient getInstance(Context context) {
        if (mInstance == null) {
            synchronized (BluetoothLeClient.class) {
                if (mInstance == null) {
                    mInstance = new BluetoothLeClient(context);
                }
            }
        }

        return mInstance;
    }

    /**
     * 检查蓝牙设备是否支持
     *
     * @param btType 蓝牙类型
     */
    public boolean checkBtDevice(BtConstants.BLUETOOTH_TYPE btType) {
        if (btType == BtConstants.BLUETOOTH_TYPE.BLE) {
            // 检查当前手机是否支持ble 蓝牙
            if (!mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE)) {
                Log.e(TAG, "not support ble device");
                return false;
            }
        }

        // For API level 18 and above, get a reference to BluetoothAdapter
        // through BluetoothManager.
        if (mBluetoothManager == null) {
            mBluetoothManager = (BluetoothManager) mContext
                    .getSystemService(Context.BLUETOOTH_SERVICE);
            if (mBluetoothManager == null) {
                Log.e(TAG, "Unable to initialize BluetoothManager.");
                return false;
            }
        }

        if (mBluetoothAdapter == null) {
            mBluetoothAdapter = mBluetoothManager.getAdapter();
            if (mBluetoothAdapter == null) {
                Log.e(TAG, "Unable to obtain a BluetoothAdapter.");
                return false;
            }
        }
        return true;
    }

    /**
     * 初始化BluetoothAdapter
     * Initializes a reference to the local Bluetooth adapter.
     *
     * @return Return true if the initialization is successful.
     */
    public boolean openBt() {
        if (mBluetoothAdapter == null) {
            Log.e(TAG, "BluetoothManager do not init");
            return false;
        }
        return mBluetoothAdapter.isEnabled() || mBluetoothAdapter.enable();
    }

    public boolean closeBt() {
        if (mBluetoothAdapter == null) {
            Log.e(TAG, "BluetoothManager do not init");
            return false;
        }
        return mBluetoothAdapter.disable();
    }

    public IBluetoothSearch getBluetoothSearcher() {
        if (mBluetoothSearcher == null) {
            synchronized (BluetoothLeClient.class) {
                if (mBluetoothSearcher == null) {
                    if (mBluetoothAdapter == null) {
                        String err = "cannot create BluetoothLeSearcher instance because not " +
                                "initialize, please call initialize() method";
                        Log.e(TAG, err);
                        return null;
                    }

                    mBluetoothSearcher = new BluetoothLeSearcher(mContext, mBluetoothAdapter, mBluetoothWorker);
                }
            }
        }

        return mBluetoothSearcher;
    }

    public BluetoothLeConnector getBluetoothLeConnector(String mac) {
        BluetoothLeConnector result;
        if ((result = mGattConnectorMap.get(mac)) != null) {
            return result;
        }

        result = new BluetoothLeConnector(mContext, mBluetoothAdapter, mac, mBluetoothWorker);
        mGattConnectorMap.put(mac, result);
        return result;
    }

    public void cleanConnector(String mac) {
        BluetoothLeConnector result;
        if ((result = mGattConnectorMap.get(mac)) != null) {
            mGattConnectorMap.remove(mac);
            result.disconnect();
            result.setOnDataAvailableListener(null);
        }
    }

    /**
     * 在不在需要连接蓝牙设备的时候，
     * 或者生命周期暂停的时候调用这一个方法
     */
    public void cleanAllConnector() {
        for (String mac : mGattConnectorMap.keySet()) {
            cleanConnector(mac);
        }
    }

    /**
     * 获取已配对蓝牙设备信息
     */
    public Set<BluetoothDevice> getBondedDevices() {
        return mBluetoothAdapter.getBondedDevices();
    }
}
