
const crc16=data=>{
    // const data=Buffer.from(text,'hex');
    let current_crc_value=0xFFFF;
    for (let i = 0; i < data.length; i++){
        current_crc_value ^= data[i] & 0xFF;
        for (let j = 0; j < 8; j++) {
            if ((current_crc_value & 1) !== 0) {
                current_crc_value = (current_crc_value >> 1) ^ 0x8408;
            } else {
                current_crc_value = current_crc_value >> 1;
            }
        }
    }

    const ab=new ArrayBuffer(2);
    new DataView(ab).setInt16(0, current_crc_value);
    const bf=Buffer.from(ab);
    bf.reverse();
    return bf;
};

const output=(()=>{
    const cmd=[];
    cmd[1]=buf=>{
        const temp={}, keys=['q','session','target','ant','scanTime'];
        for(const i in keys){
            const n=parseInt(i);
            temp[keys[i]]=buf.slice(n,n+1).readUInt8();
        }
        return temp;
    }

    const patch=buf=>{
        const temp=Buffer.concat([new Uint8Array([buf.length+2]),buf]);
        return Buffer.concat([temp,crc16(temp)]);
    }

    return {
        decode(buf){
            if(buf.readUInt8()!==buf.length-1)throw new Error('数据长度校验失败');
            if(!crc16(buf.slice(0,-2)).equals(buf.slice(-2)))throw new Error('CRC校验失败');

            const temp={},keys=['len','addr','cmd'];
            for(const i in keys){
                const n=parseInt(i);
                temp[keys[i]]=buf.slice(n,n+1).readUInt8();
            }
            if(cmd[temp.cmd])temp.data=cmd[temp.cmd](buf.slice(3,-2));

            return temp;
        },
        patch,
        send:{
            scanEpc(ant=0x80){
                const buf=Buffer.from('00 01 04 00 00 80 0a'.replace(/[\s\t]+/g,''),'hex');
                buf.set(new Uint8Array([ant]),5)
                return patch(buf);
            },
            getInfo(){
                return patch(Buffer.from('ff21','hex'));
            },
            writeEpc(text){
                if (!text || text.length % 4 !== 0 || text.length === 0) throw new Error('以字为单位输入');

                /*
                14(len)
                00(addr)
                03(cmd写数据)
                04(wNum)
                00(eNum)
                01(写入区)
                01(起始位)
                1800(PC值)
                61 62 63 64 65 66(写入数据abcdefg的hex)
                00 00 00 00（密码pwd）
                b4 1b(crc16)
                 */
                const wNum=Math.ceil(text.length/4),eNum=0;
                let m,n=text.length;
                m = n / 4;
                m = (m & 0x3F) << 3;
                const pc=`0${m.toString(16)}`.slice(-2)+'00';

                const buf=Buffer.concat([
                    new Uint8Array([0,3,wNum,eNum,1,1,pc]),
                    Buffer.from(text,'utf-8'),
                    new Uint8Array([0,0,0,0]),//password
                ]);

                return patch(buf);
            }
        },
    };
})();

const income=(()=>{
    return {
        decode(buf){
            if(buf.readUInt8()!==buf.length-1)throw new Error('数据长度校验失败');
            if(!crc16(buf.slice(0,-2)).equals(buf.slice(-2)))throw new Error('CRC校验失败');

            const data={buf,hex:buf.toString('hex')},keys=['len','addr','cmd','status',];
            for(const i in keys){
                const n=parseInt(i);
                data[keys[i]]=buf.slice(n,n+1).readUInt8();
            }

            const {cmd,status}=data;

            if((cmd===1 && status===1) || (cmd===0 && status===0)) {
                Object.assign(data, {
                    ant:buf.slice(4,5).readUInt8(),
                    num:buf.slice(5,6).readUInt8(),
                    items:[],
                });

                let index=6;
                for(let i=0;i<data.num;i++){
                    const len=buf.readUInt8(index);
                    index++;
                    const epc=buf.slice(index,index+=len),rssi=buf.slice(index,index+=1);
                    data.items.push({len,epc,rssi,hex:epc.toString('hex')});
                }
            }else if(cmd===33 && status===0){
                const keys=['master_version','slaver_version','type','Tr_Type','dmaxfre','dminfre','Power','Scntm','Ant','BeepEn'];
                for(const i in keys){
                    const n=4+parseInt(i);
                    data[keys[i]]=buf.slice(n,n+1).readUInt8();
                }
            }else data.data=buf.slice(4,-2);


            return data;
        }
    };
})();

module.exports={crc16,output,income,};