package com.bg7yoz.ft8cn;
/**
 * -----2022.5.6-----
 * MainViewModel类，用于解码FT8信号以及保存与解码有关的变量数据。生存于APP的整个生命周期。
 * 1.解码的总条数。decoded_counter和mutable_Decoded_Counter。
 * 2.解码消息的列表。消息以Ft8Message展示，列表用ArrayList泛型实现。ft8Messages，mutableFt8MessageList。
 * 3.解码和录音都需要时间同步，也就是以UTC时间的每15秒为一个周期。同步事件的触发由UtcTimer类来实现。
 * 录音方法runRecode，解码暂时用testFt8实现，后续应改为类方式。--------TODO------------
 * 4.当前的UTC时间。timerSec，更新频率（心跳频率）由UtcTimer确定，暂定100毫秒。
 * <p>
 * 5.通过类方法getInstance获取当前的MainViewModel的实例，确保有唯一的实例。
 * 6.用HamAudioRecorder类实现录音，目前只实现录音成文件，然后读取文件的数据给解码模块，后面要改成直接给数组的方式----TO DO---
 * <p>
 * 7.解码采用JNI接口调用原生C语言。调用接口名时ft8cn，由cpp文件夹下的CMakeLists.txt维护。各函数的调用接口在decode_ft8.cpp中。
 * <p>
 * -----2022.5.9-----
 * 如果系统没有发射信号，触发器会在每一个周期触发录音动作，因录音开始和结束要浪费一些时间，如果不干预上一个录音的动作，将出现
 * 连续的周期内录音动作重叠，造成第二个录音动作失败。所以，第二个周期的录音开始前，要停止前一个周期的录音，造成的结果就是每一次录音
 * 的开始时间要晚于周期开始300毫秒（模拟器的结果），实际录音的长度一般在14.77秒左右
 * <p>
 * @author BG7YOZ
 * @date 2022.5.6
 */

import static com.bg7yoz.ft8cn.GeneralVariables.getStringFromResource;

import android.annotation.SuppressLint;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothProfile;
import android.content.Context;
import android.media.AudioManager;
import android.os.Handler;
import android.util.Log;

import androidx.lifecycle.MutableLiveData;
import androidx.lifecycle.ViewModel;
import androidx.lifecycle.ViewModelProvider;
import androidx.lifecycle.ViewModelStoreOwner;

import com.bg7yoz.ft8cn.callsign.CallsignDatabase;
import com.bg7yoz.ft8cn.callsign.CallsignInfo;
import com.bg7yoz.ft8cn.callsign.OnAfterQueryCallsignLocation;
import com.bg7yoz.ft8cn.connector.BluetoothRigConnector;
import com.bg7yoz.ft8cn.connector.CableConnector;
import com.bg7yoz.ft8cn.connector.CableSerialPort;
import com.bg7yoz.ft8cn.connector.ConnectMode;
import com.bg7yoz.ft8cn.connector.FlexConnector;
import com.bg7yoz.ft8cn.connector.IComWifiConnector;
import com.bg7yoz.ft8cn.database.ControlMode;
import com.bg7yoz.ft8cn.database.DatabaseOpr;
import com.bg7yoz.ft8cn.database.OnAfterQueryFollowCallsigns;
import com.bg7yoz.ft8cn.database.OperationBand;
import com.bg7yoz.ft8cn.flex.FlexRadio;
import com.bg7yoz.ft8cn.ft8listener.FT8SignalListener;
import com.bg7yoz.ft8cn.ft8listener.OnFt8Listen;
import com.bg7yoz.ft8cn.ft8transmit.FT8TransmitSignal;
import com.bg7yoz.ft8cn.ft8transmit.OnDoTransmitted;
import com.bg7yoz.ft8cn.ft8transmit.OnTransmitSuccess;
import com.bg7yoz.ft8cn.html.LogHttpServer;
import com.bg7yoz.ft8cn.icom.IComWifiRig;
import com.bg7yoz.ft8cn.log.QSLCallsignRecord;
import com.bg7yoz.ft8cn.log.QSLRecord;
import com.bg7yoz.ft8cn.log.SWLQsoList;
import com.bg7yoz.ft8cn.rigs.BaseRig;
import com.bg7yoz.ft8cn.rigs.BaseRigOperation;
import com.bg7yoz.ft8cn.rigs.ElecraftRig;
import com.bg7yoz.ft8cn.rigs.Flex6000Rig;
import com.bg7yoz.ft8cn.rigs.FlexNetworkRig;
import com.bg7yoz.ft8cn.rigs.GuoHeQ900Rig;
import com.bg7yoz.ft8cn.rigs.IcomRig;
import com.bg7yoz.ft8cn.rigs.InstructionSet;
import com.bg7yoz.ft8cn.rigs.KenwoodKT90Rig;
import com.bg7yoz.ft8cn.rigs.KenwoodTS590Rig;
import com.bg7yoz.ft8cn.rigs.OnRigStateChanged;
import com.bg7yoz.ft8cn.rigs.XieGu6100Rig;
import com.bg7yoz.ft8cn.rigs.XieGuRig;
import com.bg7yoz.ft8cn.rigs.Yaesu2Rig;
import com.bg7yoz.ft8cn.rigs.Yaesu38Rig;
import com.bg7yoz.ft8cn.rigs.Yaesu38_450Rig;
import com.bg7yoz.ft8cn.rigs.Yaesu39Rig;
import com.bg7yoz.ft8cn.rigs.YaesuDX10Rig;
import com.bg7yoz.ft8cn.spectrum.SpectrumListener;
import com.bg7yoz.ft8cn.timer.OnUtcTimer;
import com.bg7yoz.ft8cn.timer.UtcTimer;
import com.bg7yoz.ft8cn.ui.ToastMessage;
import com.bg7yoz.ft8cn.wave.HamRecorder;
import com.bg7yoz.ft8cn.wave.OnGetVoiceDataDone;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Objects;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;


public class MainViewModel extends ViewModel {
    String TAG = "ft8cn MainViewModel";
    public boolean configIsLoaded=false;

    private static MainViewModel viewModel = null;//当前存在的实例。
    //public static Application application;


    //public int decoded_counter = 0;//解码的总条数
    public final ArrayList<Ft8Message> ft8Messages = new ArrayList<>();//消息列表
    public UtcTimer utcTimer;//同步触发动作的计时器。

    //public boolean showTrackerInfo=true;

    //public CallsignDatabase callsignDatabase = null;//呼号信息的数据库
    public DatabaseOpr databaseOpr;//配置信息，和相关数据的数据库


    public MutableLiveData<Integer> mutable_Decoded_Counter = new MutableLiveData<>();//解码的总条数
    public int currentDecodeCount = 0;//本次解码的条数
    public MutableLiveData<ArrayList<Ft8Message>> mutableFt8MessageList = new MutableLiveData<>();//消息列表
    public MutableLiveData<Long> timerSec = new MutableLiveData<>();//当前UTC时间。更新频率由UtcTimer确定，未触发时约100毫秒。
    public MutableLiveData<Boolean> mutableIsRecording = new MutableLiveData<>();//是否处于录音状态
    public MutableLiveData<Boolean> mutableHamRecordIsRunning = new MutableLiveData<>();//HamRecord是否运转
    public MutableLiveData<Float> mutableTimerOffset = new MutableLiveData<>();//本周期的时间延迟
    public MutableLiveData<Boolean> mutableIsDecoding = new MutableLiveData<>();//会触发频谱图中的标记动作
    public ArrayList<Ft8Message> currentMessages = null;//本周期解码的消息（用于画到频谱上）

    public MutableLiveData<Boolean> mutableIsFlexRadio=new MutableLiveData<>();//是不是flex电台

    private final ExecutorService getQTHThreadPool = Executors.newCachedThreadPool();
    private final ExecutorService sendWaveDataThreadPool = Executors.newCachedThreadPool();
    private final GetQTHRunnable getQTHRunnable=new GetQTHRunnable(this);
    private final SendWaveDataRunnable sendWaveDataRunnable=new SendWaveDataRunnable();


    public HamRecorder hamRecorder;//用于录音的对象
    public FT8SignalListener ft8SignalListener;//用于监听FT8信号并解码的对象
    public FT8TransmitSignal ft8TransmitSignal;//用于发射信号用的对象
    public SpectrumListener spectrumListener;//用于画频谱的对象
    public boolean markMessage = true;//是否标记消息开关

    //控制电台的方式
    public OperationBand operationBand = null;

    private SWLQsoList swlQsoList=new SWLQsoList();//用于记录SWL的QSO对象，对SWL QSO做判断，防止重复。


    public MutableLiveData<ArrayList<CableSerialPort.SerialPort>> mutableSerialPorts = new MutableLiveData<>();
    private ArrayList<CableSerialPort.SerialPort> serialPorts;//串口列表
    public BaseRig baseRig;//电台
    private final OnRigStateChanged onRigStateChanged = new OnRigStateChanged() {
        @Override
        public void onDisconnected() {
            //与电台连接中断
            ToastMessage.show(getStringFromResource(R.string.disconnect_rig));
        }

        @Override
        public void onConnected() {
            //与电台建立连接
            ToastMessage.show(getStringFromResource(R.string.connected_rig));
        }

        @Override
        public void onPttChanged(boolean isOn) {

        }

        @Override
        public void onFreqChanged(long freq) {
            //当前频率:%s
            ToastMessage.show(String.format(getStringFromResource(R.string.current_frequency)
                    , BaseRigOperation.getFrequencyAllInfo(freq)));
            //把频率的变化写回到全局变量中
            GeneralVariables.band = freq;
            GeneralVariables.bandListIndex = OperationBand.getIndexByFreq(freq);
            GeneralVariables.mutableBandChange.postValue(GeneralVariables.bandListIndex);

            databaseOpr.getAllQSLCallsigns();//通联成功的呼号读出来

        }

        @Override
        public void onRunError(String message) {
            //与电台通讯出现错误，
            ToastMessage.show(String.format(getStringFromResource(R.string.radio_communication_error)
                    , message));
        }
    };

    //发射信号用的消息列表
    //public ArrayList<Ft8Message> transmitMessages = new ArrayList<>();
    //public MutableLiveData<ArrayList<Ft8Message>> mutableTransmitMessages = new MutableLiveData<>();
    public MutableLiveData<Integer> mutableTransmitMessagesCount=new MutableLiveData<>();


    public boolean deNoise = false;//在频谱中抑制噪声

    //*********日志查询需要的变量********************
    public boolean logListShowCallsign = false;//在日志查询列表的表现形式
    public String queryKey = "";//查询的关键字
    public int queryFilter = 0;//过滤，0全部，1，确认，2，未确认
    public MutableLiveData<Integer> mutableQueryFilter = new MutableLiveData<>();
    public ArrayList<QSLCallsignRecord> callsignRecords=new ArrayList<>();
    //public ArrayList<QSLRecordStr> qslRecords=new ArrayList<>();
    //********************************************
    //关注呼号的列表
    //public ArrayList<String> followCallsign = new ArrayList<>();


    //日志管理HTTP SERVER
    private final LogHttpServer httpServer;

    /**
     * 获取MainViewModel的实例，确保存在唯一的MainViewModel实例，该实例在APP的全部生存周期中。
     *
     * @param owner ViewModelStoreOwner 所有者，一般为Activity或Fragment。
     * @return MainViewModel 返回一个MainViewModel实例
     */
    public static MainViewModel getInstance(ViewModelStoreOwner owner) {
        if (viewModel == null) {
            viewModel = new ViewModelProvider(owner).get(MainViewModel.class);
        }
        return viewModel;
    }

    /**
     * 获取消息列表中指定的消息
     *
     * @param position 在Mutable类型的列表中的位置
     * @return 返回一个Ft8Message类型的解码后的信息
     */
    public Ft8Message getFt8Message(int position) {
        return Objects.requireNonNull(ft8Messages.get(position));
    }

    /**
     * MainViewModel的构造函数主要完成一下事情：
     * 1.创建与UTC同步的时钟，时钟是UtcTimer类，内核是用Timer和TimerTask实现的。回调函数是多线程的，要考虑线程安全的问题。
     * 2.创建Mutable型的解码消息列表。
     */
    //@RequiresApi(api = Build.VERSION_CODES.N)
    public MainViewModel() {

        //获取配置信息。
        databaseOpr = DatabaseOpr.getInstance(GeneralVariables.getMainContext()
                , "data.db");
        mutableIsDecoding.postValue(false);//解码状态
        //创录音对象
        hamRecorder = new HamRecorder(null);
        hamRecorder.startRecord();

        mutableIsFlexRadio.setValue(false);

        //创建用于显示时间的计时器
        utcTimer = new UtcTimer(10, false, new OnUtcTimer() {
            @Override
            public void doHeartBeatTimer(long utc) {//不触发时的时钟信息

            }

            @Override
            public void doOnSecTimer(long utc) {//当指定间隔时触发时
                timerSec.postValue(utc);//发送当前UTC时间
                mutableIsRecording.postValue(hamRecorder.isRunning());
                mutableHamRecordIsRunning.postValue(hamRecorder.isRunning());//发送当前计时器状态
            }
        });
        utcTimer.start();//启动计时器

        //同步一下时间。microsoft的NTP服务器
        UtcTimer.syncTime(null);

        mutableFt8MessageList.setValue(ft8Messages);

        //创建监听对象，回调中的动作用于处理解码、发射、关注的呼号列表添加等操作
        ft8SignalListener = new FT8SignalListener(databaseOpr, new OnFt8Listen() {
            @Override
            public void beforeListen(long utc) {
                mutableIsDecoding.postValue(true);
            }

            @Override
            public void afterDecode(long utc, float time_sec, int sequential, ArrayList<Ft8Message> messages) {

                synchronized (ft8Messages) {
                    ft8Messages.addAll(messages);//添加消息到列表
                }
                GeneralVariables.deleteArrayListMore(ft8Messages);//删除多余的消息,FT8CN限定的可展示消息的总数量

                mutableFt8MessageList.postValue(ft8Messages);//触发添加消息的动作，让界面能观察到
                mutableTimerOffset.postValue(time_sec);//本次时间偏移量


                findIncludedCallsigns(messages);//查找符合条件的消息，放到呼叫列表中

                //检查发射程序。从消息列表中解析发射的程序
                ft8TransmitSignal.parseMessageToFunction(messages);

                mutableIsDecoding.postValue(false);//解码的状态，会触发频谱图中的标记动作

                currentMessages = messages;//保存本次解码的消息

                getQTHRunnable.messages=messages;
                getQTHThreadPool.execute(getQTHRunnable);//用线程池的方式查询归属地

                if (GeneralVariables.saveSWLMessage) {
                    databaseOpr.writeMessage(messages);//把SWL消息写到数据库
                }
                //检查QSO of SWL,并保存到SWLQSOTable中的通联列表qsoList中
                if (GeneralVariables.saveSWL_QSO){
                    swlQsoList.findSwlQso(messages, ft8Messages, new SWLQsoList.OnFoundSwlQso() {
                        @Override
                        public void doFound(QSLRecord record) {
                            databaseOpr.addSWL_QSO(record);//把SWL QSO保存到数据库
                            ToastMessage.show(record.swlQSOInfo());
                        }
                    });
                }
                //从列表中查找呼号和网格对应关系，并添加到表中
                getCallsignAndGrid(messages);
            }
        });

        ft8SignalListener.setOnWaveDataListener(new FT8SignalListener.OnWaveDataListener() {
            @Override
            public void getVoiceData(int duration, boolean afterDoneRemove, OnGetVoiceDataDone getVoiceDataDone) {
                hamRecorder.getVoiceData(duration, afterDoneRemove, getVoiceDataDone);
            }
        });


        ft8SignalListener.startListen();

        //频谱监听对象
        spectrumListener = new SpectrumListener(hamRecorder);


        //创建发射对象，回调：发射前，发射后、QSL成功后。
        ft8TransmitSignal = new FT8TransmitSignal(databaseOpr, new OnDoTransmitted() {
            @Override
            public void onBeforeTransmit(Ft8Message message, int functionOder) {
                if (GeneralVariables.controlMode == ControlMode.CAT
                        || GeneralVariables.controlMode == ControlMode.RTS
                        || GeneralVariables.controlMode == ControlMode.DTR) {
                    if (baseRig != null) {
                        if (GeneralVariables.connectMode != ConnectMode.NETWORK) stopSco();
                        baseRig.setPTT(true);
                    }
                }
                if (ft8TransmitSignal.isActivated()) {
                    GeneralVariables.transmitMessages.add(message);
                    //mutableTransmitMessages.postValue(GeneralVariables.transmitMessages);
                    mutableTransmitMessagesCount.postValue(1);
                }
            }

            @Override
            public void onAfterTransmit(Ft8Message message, int functionOder) {
                if (GeneralVariables.controlMode == ControlMode.CAT
                        || GeneralVariables.controlMode == ControlMode.RTS
                        || GeneralVariables.controlMode == ControlMode.DTR) {
                    if (baseRig != null) {
                        baseRig.setPTT(false);
                        if (GeneralVariables.connectMode != ConnectMode.NETWORK) startSco();
                    }
                }
            }

            @Override
            public void onAfterGenerate(float[] data) {
                if (GeneralVariables.connectMode == ConnectMode.NETWORK) {
                    if (baseRig != null) {
                        if (baseRig.isConnected()) {
                            sendWaveDataRunnable.baseRig=baseRig;
                            sendWaveDataRunnable.data=data;
                            //以线程池的方式执行网络数据包发送
                            sendWaveDataThreadPool.execute(sendWaveDataRunnable);
                        }
                    }
                }
            }
        }, new OnTransmitSuccess() {//当通联成功时
            @Override
            public void doAfterTransmit(QSLRecord qslRecord) {
                databaseOpr.addQSL_Callsign(qslRecord);//两个操作，把呼号和QSL记录下来
                if (qslRecord.getToCallsign() != null) {//把通联成功的分区加入到分区列表
                    GeneralVariables.callsignDatabase.getCallsignInformation(qslRecord.getToCallsign()
                            , new OnAfterQueryCallsignLocation() {
                                @Override
                                public void doOnAfterQueryCallsignLocation(CallsignInfo callsignInfo) {
                                    GeneralVariables.addDxcc(callsignInfo.DXCC);
                                    GeneralVariables.addItuZone(callsignInfo.ITUZone);
                                    GeneralVariables.addCqZone(callsignInfo.CQZone);
                                }
                            });
                }
            }
        });


        //打开HTTP SERVER
        httpServer = new LogHttpServer(this, LogHttpServer.DEFAULT_PORT);
        try {
            httpServer.start();
        } catch (IOException e) {
            Log.e(TAG, "http server error:" + e.getMessage());
        }
    }

    public void setTransmitIsFreeText(boolean isFreeText){
        if (ft8TransmitSignal!=null) {
            ft8TransmitSignal.setTransmitFreeText(isFreeText);
        }
    }
    public boolean getTransitIsFreeText(){
        if (ft8TransmitSignal!=null){
            return ft8TransmitSignal.isTransmitFreeText();
        }
        return false;
    }


    /**
     * 查找符合条件的消息，放到呼叫列表中
     *
     * @param messages 消息
     */
    private void findIncludedCallsigns(ArrayList<Ft8Message> messages) {
        Log.d(TAG, "findIncludedCallsigns: 查找关注的呼号");
        if (ft8TransmitSignal.isActivated() && ft8TransmitSignal.sequential != UtcTimer.getNowSequential()) {
            return;
        }
        int count=0;
        for (Ft8Message msg : messages) {
            //与我的呼号有关，与关注的呼号有关
            if (msg.getCallsignFrom().equals(GeneralVariables.myCallsign)
                    || msg.getCallsignTo().equals(GeneralVariables.myCallsign)
                    || GeneralVariables.callsignInFollow(msg.getCallsignFrom())
                    || (GeneralVariables.callsignInFollow(msg.getCallsignTo()) && (msg.getCallsignTo() != null))
                    || (GeneralVariables.autoFollowCQ && msg.checkIsCQ())) {//是CQ，并且允许关注CQ
                //看不是通联成功的呼号的消息
                msg.isQSL_Callsign = GeneralVariables.checkQSLCallsign(msg.getCallsignFrom());
                if (!GeneralVariables.checkIsExcludeCallsign(msg.callsignFrom)) {//不在排除呼号前缀的，才加入列表
                    count++;
                    GeneralVariables.transmitMessages.add(msg);
                }
            }
        }
        GeneralVariables.deleteArrayListMore(GeneralVariables.transmitMessages);//删除多余的消息
        //mutableTransmitMessages.postValue(GeneralVariables.transmitMessages);
        mutableTransmitMessagesCount.postValue(count);
    }

    /**
     * 清除传输消息列表
     */
    public void clearTransmittingMessage() {
        GeneralVariables.transmitMessages.clear();
        mutableTransmitMessagesCount.postValue(0);
    }


    /**
     * 从消息列表中查找呼号和网格的对应关系
     *
     * @param messages 消息列表
     */
    private void getCallsignAndGrid(ArrayList<Ft8Message> messages) {
        for (Ft8Message msg : messages) {
            if (GeneralVariables.checkFun1(msg.extraInfo)) {//检查是不是网格
                //如果内存表中没有，或不一致，就写入数据库中
                if (!GeneralVariables.getCallsignHasGrid(msg.getCallsignFrom(), msg.maidenGrid)) {
                    databaseOpr.addCallsignQTH(msg.getCallsignFrom(), msg.maidenGrid);//写数据库
                }
                GeneralVariables.addCallsignAndGrid(msg.getCallsignFrom(), msg.maidenGrid);
            }
        }
    }

    /**
     * 清除消息列表
     */
    public void clearFt8MessageList() {
        ft8Messages.clear();
        mutable_Decoded_Counter.postValue(ft8Messages.size());
        mutableFt8MessageList.postValue(ft8Messages);
    }


    /**
     * 删除单个文件
     *
     * @param fileName 要删除的文件的文件名
     */
    public static void deleteFile(String fileName) {
        File file = new File(fileName);
        // 如果文件路径所对应的文件存在，并且是一个文件，则直接删除
        if (file.exists() && file.isFile()) {
            file.delete();
        }
    }

    /**
     * 向关注的呼号列表添加呼号
     *
     * @param callsign 呼号
     */
    public void addFollowCallsign(String callsign) {
        if (!GeneralVariables.followCallsign.contains(callsign)) {
            GeneralVariables.followCallsign.add(callsign);
            databaseOpr.addFollowCallsign(callsign);
        }
    }


    /**
     * 从数据库中获取关注的呼号列表
     */
    public void getFollowCallsignsFromDataBase() {
        databaseOpr.getFollowCallsigns(new OnAfterQueryFollowCallsigns() {
            @Override
            public void doOnAfterQueryFollowCallsigns(ArrayList<String> callsigns) {
                for (String s : callsigns) {
                    if (!GeneralVariables.followCallsign.contains(s)) {
                        GeneralVariables.followCallsign.add(s);
                    }
                }
            }
        });
    }


    /**
     * 设置操作载波频率。如果电台没有连接，就有操作
     */
    public void setOperationBand() {
        if (!isRigConnected()) {
            return;
        }

        //先设置上边带，再设置频率
        baseRig.setUsbModeToRig();//设置上边带

        //此处延迟1秒发送第二个指令，是防止协谷X6100断开连接的问题
        new Handler().postDelayed(new Runnable() {
            @Override
            public void run() {
                baseRig.setFreq(GeneralVariables.band);//设置频率
                baseRig.setFreqToRig();
            }
        }, 800);
    }

    public void setCivAddress() {
        if (baseRig != null) {
            baseRig.setCivAddress(GeneralVariables.civAddress);
        }
    }

    public void setControlMode() {
        if (baseRig != null) {
            baseRig.setControlMode(GeneralVariables.controlMode);
        }
    }


    /**
     * 通过USB连接电台
     *
     * @param context context
     * @param port    串口
     */
    public void connectCableRig(Context context, CableSerialPort.SerialPort port) {
        if (GeneralVariables.controlMode == ControlMode.VOX) {//如果当前是VOX，就改成CAT模式
            GeneralVariables.controlMode = ControlMode.CAT;
        }
        connectRig();

        if (baseRig == null) {
            return;
        }
        baseRig.setControlMode(GeneralVariables.controlMode);
        CableConnector connector = new CableConnector(context, port, GeneralVariables.baudRate
                , GeneralVariables.controlMode);
        baseRig.setOnRigStateChanged(onRigStateChanged);
        baseRig.setConnector(connector);
        connector.connect();

        //晚1秒钟设置模式，防止有的电台反应不过来
        new Handler().postDelayed(new Runnable() {
            @Override
            public void run() {
                setOperationBand();//设置载波频率
            }
        }, 1000);

    }

    public void connectBluetoothRig(Context context, BluetoothDevice device) {
        GeneralVariables.controlMode = ControlMode.CAT;//蓝牙控制模式，只能是CAT控制
        connectRig();
        if (baseRig == null) {
            return;
        }
        baseRig.setControlMode(GeneralVariables.controlMode);
        BluetoothRigConnector connector = BluetoothRigConnector.getInstance(context, device.getAddress()
                , GeneralVariables.controlMode);
        baseRig.setOnRigStateChanged(onRigStateChanged);
        baseRig.setConnector(connector);

        new Handler().postDelayed(new Runnable() {//蓝牙连接是需要时间的，等2秒再设置频率
            @Override
            public void run() {
                setOperationBand();//设置载波频率
            }
        }, 5000);
    }

    public void connectIComWifiRig(Context context, IComWifiRig iComWifiRig) {
        if (GeneralVariables.connectMode == ConnectMode.NETWORK) {
            if (baseRig != null) {
                if (baseRig.getConnector() != null) {
                    baseRig.getConnector().disconnect();
                }
            }
        }

        GeneralVariables.controlMode = ControlMode.CAT;//网络控制模式
        IComWifiConnector iComWifiConnector = new IComWifiConnector(GeneralVariables.controlMode
                , iComWifiRig);
        iComWifiConnector.setOnWifiDataReceived(new IComWifiConnector.OnWifiDataReceived() {
            @Override
            public void OnWaveReceived(int bufferLen, float[] buffer) {
                hamRecorder.doOnWaveDataReceived(bufferLen, buffer);
            }

            @Override
            public void OnCivReceived(byte[] data) {

            }
        });
        iComWifiConnector.connect();
        connectRig();

        baseRig.setControlMode(GeneralVariables.controlMode);
        baseRig.setOnRigStateChanged(onRigStateChanged);
        baseRig.setConnector(iComWifiConnector);
//
        new Handler().postDelayed(new Runnable() {//蓝牙连接是需要时间的，等2秒再设置频率
            @Override
            public void run() {
                setOperationBand();//设置载波频率
            }
        }, 1000);
    }

    /**
     * 连接到flexRadio
     *
     * @param context   context
     * @param flexRadio flexRadio对象
     */
    public void connectFlexRadioRig(Context context, FlexRadio flexRadio) {
        if (GeneralVariables.connectMode == ConnectMode.NETWORK) {
            if (baseRig != null) {
                if (baseRig.getConnector() != null) {
                    baseRig.getConnector().disconnect();
                }
            }
        }
        GeneralVariables.controlMode = ControlMode.CAT;//网络控制模式
        FlexConnector flexConnector = new FlexConnector(context, flexRadio, GeneralVariables.controlMode);
        flexConnector.setOnWaveDataReceived(new FlexConnector.OnWaveDataReceived() {
            @Override
            public void OnDataReceived(int bufferLen, float[] buffer) {
                hamRecorder.doOnWaveDataReceived(bufferLen, buffer);
            }
        });
        flexConnector.connect();
        connectRig();

        baseRig.setOnRigStateChanged(onRigStateChanged);
        baseRig.setConnector(flexConnector);
//
        new Handler().postDelayed(new Runnable() {//连接是需要时间的，等2秒再设置频率
            @Override
            public void run() {
                setOperationBand();//设置载波频率
            }
        }, 3000);
    }


    /**
     * 根据指令集创建不同型号的电台
     */
    private void connectRig() {
        if ((GeneralVariables.instructionSet == InstructionSet.FLEX_NETWORK)
                || (GeneralVariables.instructionSet == InstructionSet.ICOM
                && GeneralVariables.connectMode == ConnectMode.NETWORK)) {
            hamRecorder.setDataFromLan();
        } else {
            hamRecorder.setDataFromMic();
        }
        baseRig = null;
        //此处判断是用什么类型的电台，ICOM,YAESU 2,YAESU 3
        switch (GeneralVariables.instructionSet) {
            case InstructionSet.ICOM:
                baseRig = new IcomRig(GeneralVariables.civAddress);
                break;
            case InstructionSet.YAESU_2:
                baseRig = new Yaesu2Rig();
                break;
            case InstructionSet.YAESU_3_9:
                baseRig = new Yaesu39Rig();//yaesu3代指令，9位频率
                break;
            case InstructionSet.YAESU_3_8:
                baseRig = new Yaesu38Rig();//yaesu3代指令，8位频率
                break;
            case InstructionSet.YAESU_3_450:
                baseRig = new Yaesu38_450Rig();//yaesu3代指令，8位频率
                break;
            case InstructionSet.KENWOOD_TK90:
                baseRig = new KenwoodKT90Rig();//建伍TK90
                break;
            case InstructionSet.YAESU_DX10:
                baseRig = new YaesuDX10Rig();//YAESU DX10 DX101
                break;
            case InstructionSet.KENWOOD_TS590:
                baseRig = new KenwoodTS590Rig();//KENWOOD TS590
                break;
            case InstructionSet.GUOHE_Q900:
                baseRig = new GuoHeQ900Rig();//国赫Q900
                break;
            case InstructionSet.XIEGUG90S://协谷，USB模式
                baseRig = new XieGuRig(GeneralVariables.civAddress);//协谷G90S
                break;
            case InstructionSet.ELECRAFT:
                baseRig = new ElecraftRig();//ELECRAFT
                break;
            case InstructionSet.FLEX_CABLE:
                baseRig = new Flex6000Rig();//FLEX6000
                break;
            case InstructionSet.FLEX_NETWORK:
                baseRig = new FlexNetworkRig();
                break;
            case InstructionSet.XIEGU_6100:
                baseRig = new XieGu6100Rig(GeneralVariables.civAddress);//协谷6100
                break;
        }

        mutableIsFlexRadio.postValue(GeneralVariables.instructionSet==InstructionSet.FLEX_NETWORK);

    }


    /**
     * 检察电台是否处于连接状态,两种情况：rigBaseClass没建立，串口没连接成功
     *
     * @return 是否连接
     */
    public boolean isRigConnected() {
        if (baseRig == null) {
            return false;
        } else {
            return baseRig.isConnected();
        }
    }

    /**
     * 获取串口设备列表
     */
    public void getUsbDevice() {
        serialPorts =
                CableSerialPort.listSerialPorts(GeneralVariables.getMainContext());
        mutableSerialPorts.postValue(serialPorts);
    }


    public void startSco() {
        AudioManager audioManager = (AudioManager) GeneralVariables.getMainContext()
                .getSystemService(Context.AUDIO_SERVICE);
        if (audioManager == null) return;
        if (!audioManager.isBluetoothScoAvailableOffCall()) {
            //蓝牙设备不支持录音
            ToastMessage.show(getStringFromResource(R.string.does_not_support_recording));
            return;
        }
        audioManager.setBluetoothScoOn(true);
        audioManager.startBluetoothSco();//71毫秒
        audioManager.setSpeakerphoneOn(false);//进入耳机模式
    }

    public void stopSco() {
        AudioManager audioManager = (AudioManager) GeneralVariables.getMainContext()
                .getSystemService(Context.AUDIO_SERVICE);
        if (audioManager == null) return;
        if (audioManager.isBluetoothScoOn()) {
            audioManager.setBluetoothScoOn(false);
            audioManager.stopBluetoothSco();
            audioManager.setSpeakerphoneOn(true);//退出耳机模式
        }

    }


    public void setBlueToothOn() {
        AudioManager audioManager = (AudioManager) GeneralVariables.getMainContext()
                .getSystemService(Context.AUDIO_SERVICE);
        if (audioManager == null) return;
        if (!audioManager.isBluetoothScoAvailableOffCall()) {
            //蓝牙设备不支持录音
            ToastMessage.show(getStringFromResource(R.string.does_not_support_recording));
        }

        /*
        播放音乐的对应的就是MODE_NORMAL, 如果使用外放播则调用audioManager.setSpeakerphoneOn(true)即可.
        若使用耳机和听筒,则需要先设置模式为MODE_IN_CALL(3.0以前)或MODE_IN_COMMUNICATION(3.0以后).
         */
        audioManager.setMode(AudioManager.MODE_NORMAL);//178毫秒
        audioManager.setBluetoothScoOn(true);
        audioManager.stopBluetoothSco();
        audioManager.startBluetoothSco();//71毫秒
        audioManager.setSpeakerphoneOn(false);//进入耳机模式

        //进入到蓝牙耳机模式
        ToastMessage.show(getStringFromResource(R.string.bluetooth_headset_mode));

    }

    public void setBlueToothOff() {

        AudioManager audioManager = (AudioManager) GeneralVariables.getMainContext()
                .getSystemService(Context.AUDIO_SERVICE);
        if (audioManager == null) return;
        if (audioManager.isBluetoothScoOn()) {
            audioManager.setMode(AudioManager.MODE_NORMAL);
            audioManager.setBluetoothScoOn(false);
            audioManager.stopBluetoothSco();
            audioManager.setSpeakerphoneOn(true);//退出耳机模式
        }
        //离开蓝牙耳机模式
        ToastMessage.show(getStringFromResource(R.string.bluetooth_Headset_mode_cancelled));

    }


    /**
     * 查询蓝牙是否连接
     *
     * @return 是否
     */
    @SuppressLint("MissingPermission")
    public boolean isBTConnected() {
        BluetoothAdapter blueAdapter = BluetoothAdapter.getDefaultAdapter();
        if (blueAdapter == null) return false;

        //蓝牙头戴式耳机，支持语音输入输出
        int headset = blueAdapter.getProfileConnectionState(BluetoothProfile.HEADSET);
        int a2dp = blueAdapter.getProfileConnectionState(BluetoothProfile.A2DP);
        return headset == BluetoothAdapter.STATE_CONNECTED || a2dp == BluetoothAdapter.STATE_CONNECTED;
    }

    private static class GetQTHRunnable implements Runnable {
        MainViewModel mainViewModel;
        ArrayList<Ft8Message> messages;
        public GetQTHRunnable(MainViewModel mainViewModel) {
            this.mainViewModel=mainViewModel;
        }


        @Override
        public void run() {
            CallsignDatabase.getMessagesLocation(
                    GeneralVariables.callsignDatabase.getDb(), messages);

            mainViewModel.currentDecodeCount = messages.size();
            //此变量也是告诉消息列表变化的
            mainViewModel.mutable_Decoded_Counter.postValue(
                    mainViewModel.currentDecodeCount);//告知界面消息的总数量
        }
    }
    private static class SendWaveDataRunnable implements Runnable{
        BaseRig baseRig;
        float[] data;
        @Override
        public void run() {
            if (baseRig!=null&&data!=null){
                baseRig.sendWaveData(data);//实际生成的数据是12.64+0.04,0.04是生成的0数据
            }
        }
    }

}