package cn.com.heaton.blelibrary.ble.request;

import android.annotation.TargetApi;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.le.AdvertiseCallback;
import android.bluetooth.le.AdvertiseData;
import android.bluetooth.le.AdvertiseSettings;
import android.bluetooth.le.BluetoothLeAdvertiser;
import android.os.Build;
import android.os.Handler;
import android.support.annotation.RequiresApi;

import cn.com.heaton.blelibrary.ble.BleLog;
import cn.com.heaton.blelibrary.ble.model.BleDevice;
import cn.com.heaton.blelibrary.ble.BleHandler;
import cn.com.heaton.blelibrary.ble.utils.ThreadUtils;
import cn.com.heaton.blelibrary.ble.annotation.Implement;
import cn.com.heaton.blelibrary.ble.exception.AdvertiserUnsupportException;

/**
 * TODO 2020/02/01
 * description $desc$
 * created by jerry on 2019/02/21.
 */

@Implement(AdvertiserRequest.class)
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
public class AdvertiserRequest<T extends BleDevice> {
    private static final String TAG = "AdvertiserRequest";

    private Handler mHandler = BleHandler.of();
    private BluetoothAdapter bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
    private BluetoothLeAdvertiser mAdvertiser;
    private AdvertiseSettings myAdvertiseSettings;
    private AdvertiseData myAdvertiseData;

    private void setAdvertiserSettings(){
        mAdvertiser = bluetoothAdapter.getBluetoothLeAdvertiser();
        if (mAdvertiser == null) {
            try {
                throw new AdvertiserUnsupportException("Device does not support Avertise!");
            } catch (AdvertiserUnsupportException e) {
                e.printStackTrace();
            }
        }
        //设置频率:  ADVERTISE_MODE_LOW_LATENCY 100ms     ADVERTISE_MODE_LOW_POWER 1s     ADVERTISE_MODE_BALANCED  250ms
        myAdvertiseSettings = new AdvertiseSettings.Builder()
                .setAdvertiseMode(AdvertiseSettings.ADVERTISE_MODE_LOW_LATENCY)//设置广播间隔100ms
                .setConnectable(true)
                .setTimeout(0)
                .setTxPowerLevel(AdvertiseSettings.ADVERTISE_TX_POWER_HIGH)
                .build();
    }

    public void startAdvertising(final byte[] payload, final AdvertiseSettings advertiseSettings){
        if (bluetoothAdapter.isEnabled()){
            mHandler.removeCallbacks(stopAvertiseRunnable);
            if(mAdvertiser != null){
                ThreadUtils.asyn(new Runnable() {
                    @Override
                    public void run() {
                        mAdvertiser.stopAdvertising(mAdvertiseCallback);
                        myAdvertiseData = new AdvertiseData.Builder()
                                .addManufacturerData(65520, payload)
                                .setIncludeDeviceName(true)
                                .build();
                        mAdvertiser.startAdvertising(advertiseSettings, myAdvertiseData, mAdvertiseCallback);
                    }
                });
            }
        }
    }

    public void startAdvertising(byte[] payload) {
        setAdvertiserSettings();
        startAdvertising(payload, myAdvertiseSettings);
    }

    public void stopAdvertising() {
        if (bluetoothAdapter.isEnabled()){
            if(mAdvertiser != null){
                ThreadUtils.asyn(new Runnable() {
                    @Override
                    public void run() {
                        BleLog.d(TAG, "stopAdvertising: 停止广播");
                        mAdvertiser.stopAdvertising(mAdvertiseCallback);
                    }
                });
            }
        }
    }

    public void stopAdvertising(Long delay){
        mHandler.postDelayed(stopAvertiseRunnable, delay);
    }

    private Runnable stopAvertiseRunnable = new Runnable() {
        @Override
        public void run() {
            stopAdvertising();
        }
    };

    @TargetApi(Build.VERSION_CODES.LOLLIPOP)
    private AdvertiseCallback mAdvertiseCallback = new AdvertiseCallback() {
        @Override
        public void onStartSuccess(AdvertiseSettings settingsInEffect) {
            super.onStartSuccess(settingsInEffect);
            BleLog.d(TAG, "onStartSuccess: 开启广播成功");
        }

        @Override
        public void onStartFailure(int errorCode) {
            super.onStartFailure(errorCode);
            if (errorCode == ADVERTISE_FAILED_DATA_TOO_LARGE) {
                BleLog.e(TAG, "Failed to start advertising as the advertise data to be broadcasted is larger than 31 bytes.");
            } else if (errorCode == ADVERTISE_FAILED_TOO_MANY_ADVERTISERS) {
                BleLog.e(TAG, "Failed to start advertising because no advertising instance is available.");
            } else if (errorCode == ADVERTISE_FAILED_ALREADY_STARTED) {
                BleLog.e(TAG, "Failed to start advertising as the advertising is already started");
            } else if (errorCode == ADVERTISE_FAILED_INTERNAL_ERROR) {
                BleLog.e(TAG, "Operation failed due to an internal error");
            } else if (errorCode == ADVERTISE_FAILED_FEATURE_UNSUPPORTED) {
                BleLog.e(TAG, "This feature is not supported on this platform");
            }
        }
    };
}