package com.insa.app.network;

import com.insa.app.Resources;
import com.insa.app.controller.Controller;
import javafx.application.Platform;

import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.util.logging.Level;
import java.util.logging.Logger;

public class Discoverer implements Runnable{

    private DatagramSocket socket;
    private Controller controller;
    private boolean stop;


    public Discoverer(int port, Controller ctrl) {
        try {
            socket = new DatagramSocket(port);
            controller = ctrl;
            stop = false;

            // Send broadcast to network
            DatagramPacket  packet = new DatagramPacket("discover".getBytes(),"discover".getBytes().length, Resources.getBroadcast(), Resources.discoverPort);
            Logger.getAnonymousLogger().log(Level.INFO, "Sending broadcast to : " + Resources.getBroadcast());
            socket.send(packet);
        }
        catch (Exception e) {
            Logger.getAnonymousLogger().log(Level.SEVERE, "Failed to start discover thread : " + e);
            Platform.exit();
        }
    }

    public void stop() {
        stop = true;
    }

    @Override
    public void run() {
        // Variable declaration
        byte[] bytes = new byte[1024];
        byte[] sendBytes = new byte[1024];
        String expectedContent = "discover";
        DatagramPacket packet = new DatagramPacket(bytes, bytes.length);

        // Infinite loop
        while (!stop) {
            // Try receiving a packet
            try {
                socket.receive(packet);
                InetAddress IPAddress = packet.getAddress();
                int port = packet.getPort();
                String data = new String(packet.getData(), packet.getOffset(), packet.getLength());
                if (data.equals(expectedContent) && !IPAddress.getHostAddress().equals(Resources.getMyIp())) {
                    Thread t =
                        new Thread(() -> {
                            try {
                                Thread.sleep(3000);
                                Runnable runnable = () -> {
                                    synchronized (controller) {
                                        controller.connectToUser(IPAddress.getHostAddress());
                                    }
                                };
                                Platform.runLater(runnable);
                            }
                            catch (Exception e) {

                            }

                        });
                        t.start();
                    DatagramPacket sendPacket = new DatagramPacket(sendBytes, sendBytes.length, IPAddress, port);
                    socket.send(sendPacket);
                }
            } catch (Exception e) {
                Logger.getAnonymousLogger().log(Level.SEVERE, "Failed to receive UDP packet : " + e);
            }
        }
    }
}
