package com.zd.netty.sdk;

import com.payne.connect.net.NetworkHandle;
import com.payne.reader.Reader;
import com.payne.reader.base.BaseInventory;
import com.payne.reader.bean.config.AntennaCount;
import com.payne.reader.bean.config.ProfileId;
import com.payne.reader.bean.config.Session;
import com.payne.reader.bean.receive.Failure;
import com.payne.reader.bean.receive.Success;
import com.payne.reader.bean.send.*;
import com.payne.reader.process.ReaderImpl;
import com.zd.common.core.enums.HardwareOperate;
import com.zd.common.core.exception.ServiceException;
import com.zd.netty.base.FridConsumer;
import com.zd.netty.service.ISendService;
import com.zd.netty.service.IService;
import com.zd.system.api.laboratory.RemoteLaboratoryService;
import com.zd.system.api.laboratory.domain.RemoteLabHardware;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

@Slf4j
@Service
public class WuYuanRFIDServiceImpl implements IService {

    private final Map<String, Reader> readerMap = new ConcurrentHashMap<>();
    private final Map<String, NetworkHandle> handleMap = new ConcurrentHashMap<>();
    private static final String MSG = "请先连接设备";
    private static final String SCANNER_MSG = "服务已断开，请检查连接状态正常后重启程序：";
    @Resource
    private FridConsumer fridConsumer;
    @Resource
    private ISendService sendService;
    @Resource
    private RemoteLaboratoryService laboratoryService;

    @Override
    public void start(RemoteLabHardware hardware) {
        String ipAddress = hardware.getIpAddress();
        if (!StringUtils.hasLength(ipAddress)){
            return;
        }
        Integer channels = hardware.getChannels();
        channels=channels==null?1:channels;
        Byte sessionIndex = hardware.getSessionIndex();
        sessionIndex=sessionIndex==null?0:sessionIndex;
        if (Boolean.FALSE.equals(deviceStatus(hardware))){
            connect(hardware);
            setDevice(hardware);
        }

        Reader reader;
        if (readerMap.containsKey(ipAddress)) {
            reader = readerMap.get(ipAddress);
        } else {
            throw new ServiceException(MSG);
        }
        if (reader == null || !reader.isConnected()) {
            throw new ServiceException(MSG);
        }
        stopMonitor(hardware);
        Session session = Session.valueOf(sessionIndex);
        BaseInventory inventory;
        switch (channels){
            case 4:
                inventory=new FastSwitchFourAntennaInventory.Builder().session(session)
                        .build();
                break;
            case 8:
                inventory=new FastSwitchEightAntennaInventory.Builder().session(session)
                        .build();
                break;
            case 16:
                inventory=new FastSwitchSixteenAntennaInventory.Builder().session(session)
                        .build();
                break;
            case 1:
            default:
                inventory=new FastSwitchSingleAntennaInventory.Builder().session(session)
                        .build();

        }
        log.info("============================>" + session);

        Byte index = sessionIndex;
        InventoryConfig config = new InventoryConfig.Builder()
                .setInventory(inventory)
                .setOnInventoryTagSuccess(fridConsumer)
                //读取失败
                .setOnFailure(failure -> errorMsg(failure, index, SCANNER_MSG, hardware))
                .build();
        reader.setInventoryConfig(config);
        //true -- 开启循环调用
        reader.startInventory(true);
        laboratoryService.update(HardwareOperate.OPEN,ipAddress);
    }

    @Override
    public void disconnect(RemoteLabHardware hardware) {
        Reader reader = null;
        String ipAddress = hardware.getIpAddress();
        stopMonitor(hardware);
        if (readerMap.containsKey(ipAddress)) {
            reader = readerMap.get(ipAddress);
        }
        if (reader != null && reader.isConnected()) {
            reader.disconnect();
        }

        handleMap.remove(ipAddress);
        readerMap.remove(ipAddress);
    }

    @Override
    public boolean alarm(RemoteLabHardware hardware) {
        // TODO document why this method is empty
        return false;
    }

    public Boolean deviceStatus(RemoteLabHardware hardware) {
        Reader reader = null;
        String ipAddress = hardware.getIpAddress();
        if (readerMap.containsKey(ipAddress)) {
            reader = readerMap.get(ipAddress);
        }
        return reader != null && reader.isConnected();
    }

    public void connect(RemoteLabHardware hardware) {
        Reader reader = null;
        String host = hardware.getIpAddress();
        Integer port = hardware.getPort();
        if (readerMap.containsKey(host)) {
            reader = readerMap.get(host);
        }
        if (reader != null && reader.isConnected()) {
            throw new ServiceException("设备已连接");
        }
        if (reader == null) {
            reader = ReaderImpl.create(AntennaCount.FOUR_CHANNELS);
        }
        NetworkHandle handle;
        if (handleMap.containsKey(host)) {
            handle = handleMap.get(host);
        } else {
            handle = new NetworkHandle(host, port);
            handleMap.put(host, handle);
        }
        if (reader.connect(handle)) {
            reader.getFirmwareVersion(version -> log.info("==========================reader1 version:\t" + version.getVersion()),
                    failure -> errorMsg(failure, (byte) -1, "版本获取异常：", hardware));
        } else {
            throw new ServiceException("读写器连接失败");
        }
        if (!readerMap.containsKey(host)) {
            readerMap.put(host, reader);
        }
    }

    public void setDevice(RemoteLabHardware hardware) {
        Reader reader;
        String ipAddress = hardware.getIpAddress();
        int power=33;
        String uniformPower = hardware.getUniformPower();
        String index = uniformPower.split(",")[0].split(":")[0];
        if (StringUtils.hasLength(index)){
            power= Integer.parseInt(index);
        }
        if (readerMap.containsKey(ipAddress)) {
            reader = readerMap.get(ipAddress);
        } else {
            throw new ServiceException(MSG);
        }

        stopMonitor(hardware);
        reader.setOutputPowerUniformly(
                (byte) Integer.parseInt(Integer.toHexString(power)),
                true,
                success -> successMsg(success, "设置读写器的射频输出功率"),
                failure -> errorMsg(failure, (byte) -1, "设置读写器的射频输出功率失败：", hardware));

        reader.setOutputPower(
                OutputPowerConfig.outputPower(new PowerFourAntenna.Builder().build()),
                success -> successMsg(success, "设置每个天线的射频输出功率"),
                failure -> errorMsg(failure, (byte) -1, "设置每个天线的射频输出功率失败：", hardware));

        reader.setFrequencyRegion(
                new FreqNormal.Builder().build(),
                success -> successMsg(success, "设置读写器的工作频率范围"),
                failure -> errorMsg(failure, (byte) -1, "设置读写器的工作频率范围失败：", hardware));

        reader.setRfLinkProfile(
                ProfileId.Profile1,
                success -> successMsg(success, "设置射频链路配置"),
                failure -> errorMsg(failure, (byte) -1, "设置射频链路配置失败：", hardware));

    }

    private void errorMsg(Failure failure, byte index, String msg, RemoteLabHardware hardware) {
        byte errorCode = failure.getErrorCode();
        if (errorCode == -34 && msg.equals(SCANNER_MSG) && index != -1) {
            deviceRestart(hardware);
        }
        if (errorCode == -79) {
            sendService.sendError(msg + "\t" + failure);
            stopMonitor(hardware);
            disconnect(hardware);
            if (index != -1) {
                deviceRestart(hardware);
            }
        }
    }

    public void deviceRestart(RemoteLabHardware hardware) {
        connect(hardware);
        String ipAddress = hardware.getIpAddress();
        if (readerMap.containsKey(ipAddress)) {
            Reader reader = readerMap.get(ipAddress);
            if (reader.isConnected()) {
                sendService.sendError("重连成功");
                start(hardware);
            }
            return;
        }
        throw new ServiceException("设备未连接");
    }

    public void stopMonitor(RemoteLabHardware hardware) {
        Reader reader = null;
        String ipAddress = hardware.getIpAddress();
        if (readerMap.containsKey(ipAddress)) {
            reader = readerMap.get(ipAddress);
        }
        if (reader != null && reader.isConnected()) {
            reader.stopInventory();
        }
        laboratoryService.update(HardwareOperate.CLOSE,ipAddress);
    }

    private void successMsg(Success success, String msg) {
        log.info("=========================={}：\t {}", msg, success.toString());
    }
}
