package com.yanzhenjie.andserver.sample.controller;

import android.annotation.SuppressLint;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.le.BluetoothLeScanner;
import android.os.Build;
import android.util.Log;

import androidx.annotation.RequiresApi;

import com.yanzhenjie.andserver.annotation.GetMapping;
import com.yanzhenjie.andserver.annotation.PathVariable;
import com.yanzhenjie.andserver.annotation.PostMapping;
import com.yanzhenjie.andserver.annotation.RequestMapping;
import com.yanzhenjie.andserver.annotation.RequestParam;
import com.yanzhenjie.andserver.annotation.RestController;
import com.yanzhenjie.andserver.sample.MainActivity;
import com.yanzhenjie.andserver.sample.model.ScannedDevice;
import com.yanzhenjie.andserver.sample.util.Constant;
import com.yanzhenjie.andserver.sample.util.FileUtils;
import com.yanzhenjie.andserver.sample.util.Result;
import com.yanzhenjie.andserver.sample.util.UtilsSharedPreference;
import com.yanzhenjie.andserver.util.MediaType;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.helpers.NOPLogger;

import java.util.Collection;
import java.util.HashMap;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;

import javax.validation.Valid;

import cn.jesse.nativelogger.NLogger;
import io.mega.megablelib.MegaAdvParse;
import io.mega.megablelib.MegaBleBuilder;
import io.mega.megablelib.MegaBleCallback;
import io.mega.megablelib.MegaBleClient;
import io.mega.megablelib.MegaBleConst;
import io.mega.megablelib.enums.MegaBleBattery;
import io.mega.megablelib.model.MegaBleDevice;
import io.mega.megablelib.model.bean.MegaAdvOnly;
import io.mega.megablelib.model.bean.MegaAdvertisingParsedEntity;
import io.mega.megablelib.model.bean.MegaBleHeartBeat;
import io.mega.megablelib.model.bean.MegaV2LiveSpoLive;
import io.mega.megablelib.model.bean.MegaV2LiveSpoMonitor;
import io.mega.megablelib.model.bean.MegaV2Mode;
import io.reactivex.Observable;
import io.reactivex.android.schedulers.AndroidSchedulers;

// Created by Develoven on 2023/4/23.
// Copyright (c) 2023 redflow. All rights reserved.
//
@RestController
@RequestMapping("/common")
public class CommonController extends BaseController{

    private static final String TAG = "CommonController";
    private final Long  SCAN_PERIOD = 10L;

    private static BluetoothAdapter mBluetoothAdapter;
    private static BluetoothLeScanner mScanner = null;
    //    private static BluetoothAdapter.LeScanCallback mLeScanCallback ;
    private static HashMap<String,Object> scannedDeviceList = new HashMap<>();

    private String fileName;
    MegaBleClient megaBleClient ;
    static {
//        mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
        mBluetoothAdapter = MainActivity.mBluetoothAdapter;
        if(mBluetoothAdapter == null){
            Log.e(TAG,"current device not support bluetooth");
            throw new RuntimeException("current device not support bluetooth");
        }
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            mScanner = mBluetoothAdapter.getBluetoothLeScanner();
        }

    }

    /**
     * open blue tooth :http://192.168.137.168:8080/common/open/bluetooth
     * @return
     */
    @GetMapping(value = "/open/bluetooth",produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public Result openBluetooth(){
        Log.d(TAG, fileName == null?"fileName == null":fileName);
        //1.open bluetooth
        if (mBluetoothAdapter == null) {
            Log.e(TAG, "--------------- current device not support bluetooth ");
            return fail(null,"current device not support bluetooth");
        }
        if ( !mBluetoothAdapter.isEnabled()) {
            boolean res = mBluetoothAdapter.enable();
            if (!res) {
                Log.e(TAG, "--------------- bluetooth open failed ");
                return fail(null,"bluetooth open failed");
            }
        } else if (mBluetoothAdapter.isEnabled()) {
            Log.e(TAG, "--------------- bluetooth open success");
            return fail(null,"bluetooth open success");
        }

        return success(null,"bluetooth open success");

    }
    /**
     * close bluetooth : http://192.168.137.168:8080/common/close/bluetooth
     * @return
     */
    @GetMapping(value = "/close/bluetooth",produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public Result closeBluetooth(){
        //1.close bluetooth
        if (mBluetoothAdapter == null) {
            Log.e(TAG, "--------------- current device not support bluetooth ");
            return fail(null,"current device not support bluetooth");
        }
        if ( mBluetoothAdapter.isEnabled()) {
            boolean res = mBluetoothAdapter.disable();
            if (!res) {
                Log.e(TAG, "--------------- bluetooth close failed ");
                return fail(null,"bluetooth close failed");
            }
        } else if (!mBluetoothAdapter.isEnabled()) {
            Log.e(TAG, "--------------- bluetooth close success");
            return fail(null,"bluetooth close success");
        }
        return success(null,"bluetooth close success");
    }

    /**
     * check bluetooth status : http://192.168.137.168:8080/common/status/bluetooth
     * @return
     */

    @GetMapping(value = "/status/bluetooth",produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public Result checkBluetoothStatus(){
        if (mBluetoothAdapter == null) {
            Log.e(TAG, "--------------- current device not support bluetooth ");
            return fail(null,"current device not support bluetooth");
        }else {
            return success(mBluetoothAdapter.isEnabled());
        }
    }
    /**
     * scan device by model
     * model = PULSE|ECG
     * @return
     */
    @SuppressLint("CheckResult")
    @GetMapping(value = "/scan/device/{model}",produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public Result scanDevice(@PathVariable("model") String model) throws InterruptedException {
        Log.d(TAG, fileName == null?"fileName == null":fileName);
        AtomicBoolean scanStatus = new AtomicBoolean(true);
        BluetoothAdapter.LeScanCallback mLeScanCallback = (device, rssi, scanRecord) -> {
            try{

                Log.d(TAG+"LeScan","device:{"+device.getName()+"  "+rssi+"   "+scanRecord);
                if(StringUtils.isEmpty(device.getName())) {
                    return;
                }
                if(model.equals(Constant.MODEL_PULSE)){
                    if (!device.getName().toLowerCase().contains("ring")) return;
                    if(scanRecord.length < 62) return;
                    // parse 3rd ring
                    MegaAdvOnly advOnly = MegaAdvParse.parse(scanRecord);
                    //parse 2nd ring
                    if(advOnly == null){
                        MegaAdvertisingParsedEntity advEntity = MegaBleClient.parseScanRecord(device, scanRecord);
                        if(advEntity != null){
                            Log.d(TAG,advEntity.toString());
                        }
                    }else {
                        Log.d(TAG,advOnly.toString());
                    }
                    ScannedDevice scannedDevice = new ScannedDevice(device.getName(), device.getAddress(), rssi);
                    Log.d(TAG, "device: "+scannedDevice);
                /*int index = scannedDeviceList.indexOf(scannedDevice);
                if(index == -1){
                    scannedDeviceList.add(scannedDevice);
                }else {
                    scannedDeviceList.add(index,scannedDevice);
                }*/
                    scannedDeviceList.put(scannedDevice.getAddress(),scannedDevice);
                }else if(model.equals(Constant.MODEL_ECG)){
                    if (!device.getName().toLowerCase().contains("bw-ecg")) return;
                    scannedDeviceList.put(device.getAddress(),device.getAddress());
                }

            }catch (Exception e ){
                Log.d(TAG,e.getMessage());
                e.printStackTrace();
            }
        };
        Log.d(TAG,"model="+model);
        //scan PULSE device
        Log.d(TAG,"size---"+scannedDeviceList.size());
        if(scannedDeviceList.size()>0){
            scannedDeviceList.clear();
        }
        Log.d(TAG,"size---"+scannedDeviceList.size());
        //scan ecg device
        Observable.timer(SCAN_PERIOD,TimeUnit.SECONDS).subscribe( aLong -> {
            mBluetoothAdapter.stopLeScan(mLeScanCallback);
            scanStatus.set(false);
            Log.d(TAG,"scannedDeviceList.size---"+scannedDeviceList.size());
        });
        Log.d(TAG,"mLeScanCallback---"+mLeScanCallback);
        Log.d(TAG,"mBluetoothAdapter---"+mBluetoothAdapter);
        Log.i(TAG,"开始扫描");
        mBluetoothAdapter.startLeScan(mLeScanCallback);
        Observable.interval(1,TimeUnit.SECONDS).take(SCAN_PERIOD).observeOn(AndroidSchedulers.mainThread()).subscribe(aLong ->{
            Log.d(TAG,aLong.toString()+"scanning...");

        });
        /*switch (model){

            case Constant.MODEL_ECG:

                break ;
            case Constant.MODEL_PULSE:
                Log.d(TAG,"model=PULSE");
                //scan PULSE device
                Log.d(TAG,"size---"+scannedDeviceList.size());
                if(scannedDeviceList.size()>0){
                    scannedDeviceList.clear();
                }
                Log.d(TAG,"size---"+scannedDeviceList.size());
                //scan ecg device
                Observable.timer(SCAN_PERIOD,TimeUnit.SECONDS).subscribe( aLong -> {
                    mBluetoothAdapter.stopLeScan(mLeScanCallback);
                    scanStatus.set(false);
                    Log.d(TAG,"scannedDeviceList.size---"+scannedDeviceList.size());
                });
                Log.d(TAG,"mLeScanCallback---"+mLeScanCallback);
                Log.d(TAG,"mBluetoothAdapter---"+mBluetoothAdapter);
                Log.i(TAG,"开始扫描");
                mBluetoothAdapter.startLeScan(mLeScanCallback);
                Observable.interval(1,TimeUnit.SECONDS).take(SCAN_PERIOD).observeOn(AndroidSchedulers.mainThread()).subscribe(aLong ->{
                    Log.d(TAG,aLong.toString()+"scanning...");

                });
                break;
        }*/
        while (scanStatus.get()){
            Thread.sleep(1000);
            Log.d(TAG, scanStatus+"---"+System.currentTimeMillis()+"----");
            Log.i(TAG,"等待");
        }

        return success(scannedDeviceList.values());
    }

    /**
     * connect bluetooth
     * @return
     */
    @PostMapping(value = "/connect/bluetooth/{model}",produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public Result connectBluetooth(@Valid @RequestParam(name = "mac") String mac,@Valid @RequestParam(name = "name") String name){
        Log.i(TAG,mac);
        fileName = "测试文件名称";
        MegaBleCallback megaBleCallback = new MegaBleCallback() {
            @Override
            public void onConnectionStateChange(boolean connected, MegaBleDevice device) {
                super.onConnectionStateChange(connected, device);
                //状态变更 ：通知前台服务
                if(connected){
                    Log.d(TAG, "已连接："+device);
                }else {
                    Log.d(TAG, "断开连接");
                }
            }
            @Override
            public void onError(int code) {
                NLogger.e(TAG,"error code :{}",code);
            }

            @Override
            public void onStart() {
                String userId = "5837288dc59e0d00577c5f9a";
                String token = UtilsSharedPreference.get(MainActivity.context,UtilsSharedPreference.KEY_TOKEN);
                if(StringUtils.isEmpty(token)){
                    megaBleClient.startWithToken(userId, "0,0,0,0,0,0");
                }else {
                    megaBleClient.startWithToken(userId, token);
                }
            }

            @Override
            public void onDeviceInfoReceived(MegaBleDevice device) {
                megaBleClient.getV2Batt();
                megaBleClient.getV2Mode();
                megaBleClient.enableV2ModeSpoMonitor(true);
            }
            @Override
            public void onSetUserInfo() {
                megaBleClient.setUserInfo((byte) 25, (byte) 1, (byte) 170, (byte) 60, (byte) 0);
            }

            @Override
            public void onIdle() {
                // 设备闲时，可开启实时、开启长时监控、收监控数据。
                // 长时监控数据会被记录到戒指内部，实时数据不会。
                // 长时监控开启后，可断开蓝牙连接，戒指将自动保存心率血氧数据，以便后续手机连上收取。默认每次连上会同步过来。
                // 绑定token有变动时，用户信息，监测数据将被清空。
                // 建议默认开启全局实时通道，无需关闭，重复开启无影响
                // suggested setting, repeated call is ok.
                Log.d(TAG, "Important: the remote device is idle.");
                megaBleClient.toggleLive(true);
            }

            @Override
            public void onV2LiveSpoLive(MegaV2LiveSpoLive live) {

            }

            @Override
            public void onV2LiveSpoMonitor(MegaV2LiveSpoMonitor live) {
               /* switch (live.getStatus()){
                    case MegaBleConst.STATUS_LIVE_VALID:
                        updateV2Live(live);
                        break;
                    case MegaBleConst.STATUS_LIVE_PREPARING
                        updateV2Live(live);
                    break;
                    case MegaBleConst.STATUS_LIVE_INVALID
                            updateV2Live(live);
                    break;

                }*/
            }

            //notice user to shaking ,in order to bind the ring
            @Override
            public void onKnockDevice() {

            }

            @Override
            public void onTokenReceived(String token) {
                UtilsSharedPreference.put(MainActivity.context, UtilsSharedPreference.KEY_TOKEN, token);
            }

            //notice UI modify rssi
            @Override
            public void onRssiReceived(int rssi) {

            }

            /**
             * notify front to change battery value & battery status
             *
             * @param value 电池电量
             * @param status 电池状态  normal(0, "normal"), charging(1, "charging"),full(2, "full"),lowPower(3, "lowPower");error(4, "error");shutdown(5, "shutdown");
             */
            @Override
            public void onBatteryChanged(int value, int status) {
//                MegaBleBattery.getDescription(status);
            }

            /**
             * notify front active mode
             * @param mode
             */
            @Override
            public void onV2ModeReceived(MegaV2Mode mode) {

            }

            /**
             * 心跳检测，检测到心跳就开启脉搏
             * @param heartBeat
             */
            @Override
            public void onHeartBeatReceived(MegaBleHeartBeat heartBeat) {

            }

            @Override
            public void onRawdataParsed(int[][] a) {
                if(a != null && a.length > 0){
                    for (int[] ints : a) {
                        FileUtils.addFile(MainActivity.context.getFilesDir().getPath() + "/脉诊'", String.valueOf(ints[0]));
                    }
                }
            }
        };
        // mock id, key，use yours
        MegaBleBuilder builder = new MegaBleBuilder();
        try{
            megaBleClient = builder
                    .withSecretId("D4CE5DD515F81247")
                    .withSecretKey("uedQ2MgVEFlsGIWSgofHYHNdZSyHmmJ5")
                    .withContext(MainActivity.context)
                    .withCallback(megaBleCallback)
                    .build();
        }catch (Exception e ){
            e.printStackTrace();
        }
        // 开发测试时，可以开启debug
        megaBleClient.setDebugEnable(true);
        megaBleClient.connect(mac, name);

        return success();
    }


 /*   //初始化蓝牙广播
    private void initBroadcast(){
        broadcastReceiver = new CustomBroadcastReceiver();
        IntentFilter intentFilter = new IntentFilter();
        intentFilter.addAction(BluetoothAdapter.ACTION_DISCOVERY_STARTED); //开始扫描
        intentFilter.addAction(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);//扫描结束
        intentFilter.addAction(BluetoothDevice.ACTION_FOUND);//搜索到设备
        intentFilter.addAction(BluetoothDevice.ACTION_BOND_STATE_CHANGED); //配对状态监听
        registerReceiver(broadcastReceiver,intentFilter);
    }*/


}
