package com.asreader.asr033w.asr033w.network;

import com.asreader.asr033w.asr033w.Constants;
import com.asreader.asr033w.asr033w.errormodel.ASR033WErrorCode;
import com.asreader.asr033w.asr033w.errormodel.ASR033WErrorModel;
import com.asreader.asr033w.asr033w.info.ASR033WReaderInfo;
import java.net.DatagramPacket;
import java.net.InetAddress;
import java.net.MulticastSocket;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;

public class ASR033WNetworkUDP {
    private String BIND_GROUP_IP = "230.1.1.169"; // 组播地址
    private int BIND_GROUP_PORT = 8161; // 组播端口
    private int PACK_SIZE = 1024;
    private ASR033WNetworkUDPCallBack callBack;
    MulticastSocket socket = null;
    boolean isTimeOutCheck = true;
    int isTimeOutCheckCount = 0;

    public void setCallBack(ASR033WNetworkUDPCallBack callBack) {
        this.callBack = callBack;
    }

    public void searchDevice() {
        if(socket != null){
            if (socket.isClosed() == true){
                socket.close();
            }
            socket = null;
        }
        isTimeOutCheck = true;
        isTimeOutCheckCount = 0;
        int timeout = ASR033WReaderInfo.getInstance().searchTimeout;
        if (timeout == 0){
            timeout = 10;
        }
        final int maxTimeOut = timeout;
        new Thread(() -> {
            while (isTimeOutCheck){
                try {
                    Thread.sleep(1 * 1000);
                } catch (InterruptedException e) {

                }
                isTimeOutCheckCount = isTimeOutCheckCount + 1;

                if (isTimeOutCheckCount > maxTimeOut){
                    break;
                }
            }
            finishSearchDevice();
        }).start();

        new Thread(() -> {
            try {
                socket = new MulticastSocket(BIND_GROUP_PORT);
                socket.setSoTimeout(20*1000);
                InetAddress group = InetAddress.getByName(BIND_GROUP_IP);
                socket.joinGroup(group);
                byte[] buffer = new byte[PACK_SIZE];
                DatagramPacket packet = new DatagramPacket(buffer, buffer.length);
                while (true) {
                    socket.receive(packet);
                    String message = new String(packet.getData(), 0, packet.getLength());
                    if(message.length() != 0){
                        String[] items = message.split(",");
                        HashMap<String, String> dictionary = new HashMap<>();
                        for (String item: items) {
                            String[] bodyArray = item.split(":");
                            ArrayList<String> arrayList = new ArrayList<>(Arrays.asList(bodyArray));
                            if (arrayList.size() == 2) {
                                String string = arrayList.get(0);
                                if (string.contains(Constants.SEARCH_RFID_READER_INFORMATION)) {
                                    dictionary.put(Constants.SEARCH_RFID_READER_INFORMATION, arrayList.get(1));
                                }
                                if (string.contains(Constants.SEARCH_IP)) {
                                    dictionary.put(Constants.SEARCH_IP, arrayList.get(1));
                                }
                                if (string.contains(Constants.SEARCH_MASK)) {
                                    dictionary.put(Constants.SEARCH_MASK, arrayList.get(1));
                                }
                                if (string.contains(Constants.SEARCH_GATEWAY)) {
                                    dictionary.put(Constants.SEARCH_GATEWAY, arrayList.get(1));
                                }
                                if (string.contains(Constants.SEARCH_MAC)) {
                                    dictionary.put(Constants.SEARCH_MAC, arrayList.get(1));
                                }
                                if (string.contains(Constants.SEARCH_PORT)) {
                                    dictionary.put(Constants.SEARCH_PORT, arrayList.get(1));
                                }
                                if (string.contains(Constants.SEARCH_HOST_SERVER_IP)) {
                                    String ipString = arrayList.get(1);
                                    if (ipString.contains("\r\n")) {
                                        ipString = ipString.replace("\r\n", "");
                                    }
                                    dictionary.put(Constants.SEARCH_HOST_SERVER_IP, ipString);
                                }
                                if (string.contains(Constants.SEARCH_HOST_SERVER_PORT)) {
                                    dictionary.put(Constants.SEARCH_HOST_SERVER_PORT, arrayList.get(1));
                                }
                                if (string.contains(Constants.SEARCH_MODE)) {
                                    dictionary.put(Constants.SEARCH_MODE, arrayList.get(1));
                                }
                                if (string.contains(Constants.SEARCH_NET_STATE)) {
                                    dictionary.put(Constants.SEARCH_NET_STATE, arrayList.get(1));
                                }
                                if (string.contains(Constants.SEARCH_DHCP_SW)) {
                                    dictionary.put(Constants.SEARCH_DHCP_SW, arrayList.get(1));
                                }
                            }
                        }
                        if (this.callBack != null){
                            this.callBack.onSearchingUDPReceiveInformation(dictionary,false);
                        }
                     }
                }
            } catch (Exception e) {
                ASR033WErrorModel errorModel =  new ASR033WErrorModel("udp", ASR033WErrorCode.ASR033WErrorCodeNil_Instance);
                if (this.callBack != null){
                    this.callBack.onReceivedUDPSearchError(errorModel);
                }
            }
        }).start();
    }

    private void finishSearchDevice() {
        stopSearch();
        if (this.callBack != null){
            this.callBack.onSearchingUDPReceiveInformation(null,true);
        }
    }
    public void stopSearch() {
        isTimeOutCheck = false;
        if(socket != null){
            if (socket.isClosed() == true){
                socket.close();
            }
            socket = null;
        }
    }
}
