package cgmblelib.custom.livedata;

import android.os.Build;

import java.util.ArrayList;
import java.util.Hashtable;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicBoolean;

import cgmblelib.custom.livedata.connect.EnumConnect;
import cgmblelib.custom.livedata.connect.OperationConnectLiveData;
import cgmblelib.custom.livedata.scan.EnumScan;
import cgmblelib.custom.livedata.scan.OperationScanLiveData;
import cgmblelib.custom.livedata.scan.PocDeviceAndRssi;
import cgmblelib.database.entity.PocDevice;
import cgmblelib.utils.MyLog;

/**
 * 自定义LiveData控制类
 * @author minyuchun
 */
public class ManagementLiveData {

    private Map<Integer, OperationScanLiveData.OperationScanListener> mScanListenerMap = new Hashtable<>();

    private Map<Integer, OperationConnectLiveData.OperationConnectListener> mConnectListenerMap = new Hashtable<>();

    private OperationScanLiveData.OperationScanListener mScanListener = null;

    private OperationConnectLiveData.OperationConnectListener mConnectListener = null;

    private List<PocDevice> mDeviceList;

    private ManagementLiveData() {}
    private static class SingletonInstance {
        private static final ManagementLiveData INSTANCE = new ManagementLiveData();
    }
    public static ManagementLiveData getInstance() {
        return SingletonInstance.INSTANCE;
    }

    public void requestOperationScan(OperationScanLiveData.OperationScanListener listener){
        mScanListener = listener;
    }

    public void removeOperationScan(){
        mScanListener = null;
    }

    public int requestOperationScanUpdate(OperationScanLiveData.OperationScanListener listener){
        int listerId = mScanListenerMap.size() + 1;
        mScanListenerMap.put(listerId,listener);
        if (mScanListenerMap.containsKey(listerId)){
            return listerId;
        }
        return 0;
    }

    public boolean removeOperationScanUpdate(int mapKey, OperationScanLiveData.OperationScanListener listener){
        if (mScanListenerMap.containsKey(mapKey)){
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
                return mScanListenerMap.remove(mapKey,listener);
            } else {
                return mScanListenerMap.remove(mapKey) != null;
            }
        }
        return false;
    }


    public synchronized void updateOperationScan(EnumScan scan){
        try {
            if (scan == null){
                return;
            }
            if (scan == EnumScan.SCAN_START){
                mDeviceList = new ArrayList<>();
            }
            if (mScanListenerMap != null && !mScanListenerMap.isEmpty()){
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
                    mScanListenerMap.forEach((integer, listener) -> listener.onChanged(scan,null));
                } else {
                    for (OperationScanLiveData.OperationScanListener listener : mScanListenerMap.values()) {
                        listener.onChanged(scan, null);
                    }
                }
            }
            if (mScanListener != null){
                MyLog.d("updateOperationScan " + scan);
                mScanListener.onChanged(scan, null);
            } else {
                MyLog.d("mScanListener is NUll " + scan);
            }
        } catch (Exception e){
            e.printStackTrace();
        }
    }

    public synchronized void updateOperationScan(PocDevice pocDevice, int rssi){
        if (pocDevice == null){
            return;
        }
        if (mDeviceList == null){
            mDeviceList = new ArrayList<>();
        }
        if (mScanListenerMap != null && !mScanListenerMap.isEmpty()){
            AtomicBoolean sameAddress = new AtomicBoolean(false);
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
                mDeviceList.forEach(device -> {
                    if (device.getAddress().equals(pocDevice.getAddress())){
                        sameAddress.set(true);
                    }
                });
                if (!sameAddress.get()){
                    mDeviceList.add(pocDevice);
                    mScanListenerMap.forEach((integer, listener) -> listener.onChanged(EnumScan.SCAN_IN,new PocDeviceAndRssi(pocDevice,rssi)));
                }
            } else {
                for (PocDevice device:mDeviceList){
                    if (device.getAddress().equals(pocDevice.getAddress())){
                        sameAddress.set(true);
                    }
                }
                if (!sameAddress.get()) {
                    mDeviceList.add(pocDevice);
                    for (OperationScanLiveData.OperationScanListener listener : mScanListenerMap.values()) {
                        listener.onChanged(EnumScan.SCAN_IN, new PocDeviceAndRssi(pocDevice,rssi));
                    }
                }
            }

        }

        if (mScanListener != null) {
            AtomicBoolean sameAddress = new AtomicBoolean(false);
            for (PocDevice device : mDeviceList) {
                if (device.getAddress().equals(pocDevice.getAddress())) {
                    sameAddress.set(true);
                }
            }
            if (!sameAddress.get()) {
                mDeviceList.add(pocDevice);
//                MyLog.i("updateOperationScan " + pocDevice.toString());
                mScanListener.onChanged(EnumScan.SCAN_IN, new PocDeviceAndRssi(pocDevice,rssi));
            } else {
                MyLog.e("sameAddress = " + sameAddress.get());
            }
        } else {
            MyLog.e("mScanListener is null");
        }
    }


    public void requestOperationConnect(OperationConnectLiveData.OperationConnectListener listener){
        mConnectListener = listener;
    }

    public void removeOperationConnect(){
        mConnectListener = null;
    }


    public int requestOperationConnectUpdate(OperationConnectLiveData.OperationConnectListener listener){
        int listerId = mScanListenerMap.size() + 1;
        mConnectListenerMap.put(listerId,listener);
        if (mConnectListenerMap.containsKey(listerId)){
            return listerId;
        }
        return 0;
    }

    public boolean removeOperationConnectUpdate(int mapKey, OperationConnectLiveData.OperationConnectListener listener){
        if (mConnectListenerMap.containsKey(mapKey)){
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
                return mConnectListenerMap.remove(mapKey,listener);
            } else {
                return mConnectListenerMap.remove(mapKey) != null;
            }
        }
        return false;
    }

    public void updateOperationConnect(EnumConnect connect){
        if (connect == null){
            return;
        }
        if (mConnectListenerMap != null && !mConnectListenerMap.isEmpty()){
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
                mConnectListenerMap.forEach((integer, operationConnectListener) -> operationConnectListener.onChanged(connect,0));
            } else {
                for (OperationConnectLiveData.OperationConnectListener operationConnectListener: mConnectListenerMap.values()) {
                    operationConnectListener.onChanged(connect,0);
                }
            }
        }
        if (mConnectListener != null){
            mConnectListener.onChanged(connect,0);
        }
    }

    public void updateOperationConnect(int glucoseId){
        if (mConnectListenerMap != null && !mConnectListenerMap.isEmpty()){
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
                mConnectListenerMap.forEach((integer, operationConnectListener) -> operationConnectListener.onChanged(EnumConnect.CONNECT_PULL_IN,glucoseId));
            } else {
                for (OperationConnectLiveData.OperationConnectListener operationConnectListener: mConnectListenerMap.values()) {
                    operationConnectListener.onChanged(EnumConnect.CONNECT_PULL_IN,glucoseId);
                }
            }
        }
        if (mConnectListener != null){
            mConnectListener.onChanged(EnumConnect.CONNECT_PULL_IN,glucoseId);
        }
    }
}
