package com.bpa.scalage.HBL.Communication;

import com.bpa.scalage.HBL.DataUtil.NotifyPropVar;
import com.bpa.scalage.HBL.Result.OperateResult;
import com.bpa.scalage.HBL.Result.OperateResultT;
import com.bpa.scalage.HBL.Result.ResultCode;
import com.bpa.scalage.HBL.Thread.IThread;
import com.bpa.scalage.HBL.Thread.ThreadManager;
import com.bpa.scalage.helper.ByteHelper;
import com.bpa.scalage.HBL.Interface.IRun;
import com.bpa.scalage.HBL.Interface.IRunT;
import com.pc_rfid.api.SerialPort;

import java.util.Arrays;
import java.util.concurrent.ConcurrentLinkedQueue;

/**
 * 称重台操作类
 */
public class WeightHelper {
    private static SerialPort COM=null;
    private static boolean mRunning = false;
    private static boolean mCartRunning = false;
    private static ConcurrentLinkedQueue<Byte> cache = new ConcurrentLinkedQueue<>();
    private static ConcurrentLinkedQueue<byte[]> sendbuffer=new ConcurrentLinkedQueue<>();
    public static IRunT<Integer> DataUpdate;
    public static NotifyPropVar<Integer> WeightNotify=new NotifyPropVar<>(0);
    private static IRun CloseNotify;
    private static int  weight=0;
    public static boolean IsConnect(){
        return COM==null?false:COM.isOpen;
    }

    private static void Sleep(long time){
        try{
            Thread.sleep(time);
        }catch(InterruptedException e){};
    }

    private static void getDataTask(){
        ThreadManager.get().StartLong("称重台数据获取", true, new IThread() {
            @Override
            public void Run() throws InterruptedException {
                readBytes().OnSource(data->{
                    for (int i = 0; i < data.Content.length; i++)
                        cache.add(data.Content[i]);
                });
                getCardData();
                Thread.sleep(1);
            }
            @Override
            public void RunComplete() throws InterruptedException {
               if(IsConnect()) COM.Close();
                mCartRunning=false;
                if(CloseNotify!=null)CloseNotify.Run();
            }
        });
    }

    public static OperateResult Open(String comName, int baud, String format ){
        Close(null);
        try{
            COM = new SerialPort(comName, baud, 8, 'N', 1);
            if(IsConnect()){
                mCartRunning=true;
                getDataTask();
                return OperateResult.CreateSuccess();
            }
        }catch(Exception e){
            return OperateResult.CreateFailed("打开串口失败");
        }
        return OperateResult.CreateFailed("打开串口失败");
    }

    public static void Close(IRun closeNotify) {
        CloseNotify=closeNotify;
        ThreadManager.get().Stop("称重台数据获取");
    }

    public static void Close() {
        ThreadManager.get().Stop("称重台数据获取");
    }


    public static OperateResult ZeroClear(){
        if(IsConnect()){
            byte[] rFRead=new byte[5];
            rFRead[0] = 0x01;
            rFRead[1] = 0x03;
            rFRead[2] = 0x54;
            rFRead[3] = 0x21;
            rFRead[4] = 0x0f;
//            sendbuffer.add(rFRead);
           int res = COM.write(rFRead,rFRead.length);
           if(res==0) return OperateResult.CreateSuccess();
           else return OperateResult.CreateFailed("写入失败");
        }else return OperateResult.CreateFailed("写入失败,设备未连接");
    }

    private static OperateResultT<byte[]> readBytes() {
        try {
            if(IsConnect()){
//                while   (sendbuffer.size()>0){
//                    COM.clearBuffer();
//                    byte[] sendBuffer = sendbuffer.poll();
//                    COM.write(sendBuffer,sendBuffer.length);
//                    Sleep(500);
//                }

                byte[] buffer = new byte[1024];
                int len = COM.read(buffer);
                if(len>0) return OperateResultT.CreateSuccess(Arrays.copyOfRange(buffer, 0, len));
                else  return new OperateResultT<>(ResultCode.Fail);
            }else return OperateResultT.CreateFailedT("写入失败,设备未连接");
        } catch (Exception e) {
            return OperateResultT.CreateFailedT(e);
        }
    }

    private static void getCardData(){
        byte[] temp = new byte[12];
        while (cache.size() >= 12) {
            byte flag = cache.poll();
            if (flag != 0x01) continue;
            byte cmd = cache.poll();
            if (cmd != 0x03) continue;
            temp[0] = 0x01;
            temp[1] = 0x03;
            for (int i = 2; i < 12; i++) {
                temp[i] = cache.poll();
            }
            //  01 03 2B 30 30 31 2E 30 30 30 23 9D
            //模块功能  +  0  0  1  .  0  0  0  校验
            //1KG显示+001.000ASCII代码编写
            //+代表2B -2E
            //0代表30
            //1代表31
            //.小数点代表2E

            //取前10位 计算校验码
            byte[] validateTemp = new byte[10];
            System.arraycopy(temp, 0, validateTemp, 0, 10);
            int res = ByteHelper.getCRC2(validateTemp);
            //取后两位校验码
            byte[] rawCode = new byte[4];
            System.arraycopy(temp, 10, rawCode, 2, 2);
            int raw = ByteHelper.byteToInt(rawCode);
            if (raw == res) //校验成功
            {
                //+001.000 heavy[2]==0x2B
                final byte[] heavy = new byte[7];
                System.arraycopy(temp, 3, heavy, 0, 7);
                String text = new String(heavy);
                int zl=0;
                if(temp[2]==0x2B){
                    weight= (int) (Double.parseDouble(text)*1000);//如果是正数
                }else{
                    weight= (int) (Double.parseDouble(text)*1000*-1);
                }
                if(DataUpdate!=null)DataUpdate.Run(weight);
                WeightNotify.setValue(weight);
            }
        }
    }

}
