package DataLayer;

import FunctionLayer.Datahandler;
import edu.stanford.nlp.pipeline.StanfordCoreNLP;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.*;
import java.util.ArrayList;
import java.util.Properties;

public class ThreadClient {
    public ThreadClient(Datahandler datahandler, StanfordCoreNLP stanfordCoreNLP, StanfordCoreNLP stanfordCoreNLPSentiment) {
        ArrayList<Integer> ports = new ArrayList<Integer>();
        ports.add(48475);
        ports.add(48476);
        ports.add(48477);
        ports.add(48478);

        Properties prop = new Properties();
        String fileName = "app.config";
        try (FileInputStream fis = new FileInputStream(fileName)) {
            prop.load(fis);
        } catch (FileNotFoundException ex) {
        } catch (IOException ex) {
        }

        String hostIP = prop.getProperty("app.hostip");
        String hostIP2 = prop.getProperty("app.hostip2");
        try {
            InetAddress ipAddress = InetAddress.getByName(hostIP);//used ip's
            InetAddress ipAddress2 = InetAddress.getByName(hostIP2);//used ip's
            try (DatagramSocket serverSocket = new DatagramSocket(ports.get(0))) {
                try (DatagramSocket serverSocket1 = new DatagramSocket(ports.get(1))) {
                    try (DatagramSocket serverSocket2 = new DatagramSocket(ports.get(2))) {
                        try (DatagramSocket serverSocket3 = new DatagramSocket(ports.get(3))) {
                            while (true) {
                                try {
                                    receiveAndSendPacket(serverSocket, ipAddress, ports.get(0), datahandler, stanfordCoreNLP, stanfordCoreNLPSentiment);
                                    receiveAndSendPacket(serverSocket1, ipAddress, ports.get(1), datahandler, stanfordCoreNLP, stanfordCoreNLPSentiment);
                                    receiveAndSendPacket(serverSocket2, ipAddress2, ports.get(2), datahandler, stanfordCoreNLP, stanfordCoreNLPSentiment);
                                    receiveAndSendPacket(serverSocket3, ipAddress2, ports.get(3), datahandler, stanfordCoreNLP, stanfordCoreNLPSentiment);
                                } catch (IOException e) {
                                    throw new RuntimeException(e);
                                }
                            }
                        }
                    }
                }
            } catch (SocketException e) {
                e.printStackTrace();
            }
        } catch (UnknownHostException e) {
            e.printStackTrace();
        }
    }

    private static void receiveAndSendPacket(DatagramSocket serverSocket, InetAddress ipAddress, int port,
                                             Datahandler datahandler, StanfordCoreNLP stanfordCoreNLP, StanfordCoreNLP stanfordCoreNLPSentiment) throws
            IOException {
        byte[] receiveData = new byte[4096];
        DatagramPacket receivePacket = new DatagramPacket(receiveData, receiveData.length);
        try {
            /*
            Only one DatagramSocket can call receive at a time since its a blocking call. yet somehow
            the other DatagramSockets still get their UDP packets from receive() even if the call is made
            many minutes after the actual UDP packet was sent. Maybe Security manager context?
             */
            serverSocket.receive(receivePacket);
        } catch (IOException e) {
            e.printStackTrace();
        }
        String sentence = new String(receivePacket.getData(), 0,
                receivePacket.getLength());
        sentence = sentence.replace("clientmessage:", "");
        String ResponseMsg = datahandler.getResponseMsg(sentence, "", stanfordCoreNLP, stanfordCoreNLPSentiment,
                true);
        System.out.println("port: " + port + ". ResponseMsg ingame: " + ResponseMsg);
        byte[] sendData = new byte[0];
        try {
            sendData = ResponseMsg.getBytes("UTF-8");
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        int deliver_port = 0;
        switch (port) {
            case 48475:
                deliver_port = 48470;
                break;
            case 48476:
                deliver_port = 48471;
                break;
            case 48477:
                deliver_port = 48472;
                break;
            case 48478:
                deliver_port = 48473;
                break;
        }
        DatagramPacket sendPacket = new DatagramPacket(sendData, sendData.length, ipAddress, deliver_port);
        try {
            serverSocket.send(sendPacket);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
