package org.artisanlogiciel.games.minetest.net;

import org.artisanlogiciel.games.minetest.core.PacketException;

import java.io.IOException;
import java.net.*;

/**
 * Man in the middle UDP
 * very simple for one client only
 */

public class MiM {

    DatagramSocket serverSocket;
    boolean running = false;
    InetSocketAddress serverAddress;
    // will be captured, incoming address & port
    SocketAddress fromClient = null;
    int localPort;
    PacketHandler handler = null;

    public MiM(int myPort, InetSocketAddress remoteAddress)
    {
        localPort = myPort;
        serverAddress = remoteAddress;
    }

    public void launch()
    {
        // ServerSocket socket = new ServerSocket()
        try {
            handler = new PacketHandler();
            serverSocket = new DatagramSocket(localPort);
            DatagramSocket in = serverSocket;
            SocketAddress fromServer = serverAddress;
            Thread toServer = new Thread( () -> {runFromToServer(in,fromServer);});
            running = true;
            toServer.start();
        }
        catch(Exception e)
        {
            System.out.println("problem");
            e.printStackTrace(System.err);
            running = false;
        }
    }

    public void stop()
    {
        running = false;
    }

    public void runFromToServer(DatagramSocket in, SocketAddress fromServer) {
        try {

            while (running) {
                // quick way, a new buffer at each reception
                // to handle split packets that are buffered
                byte[] buf = new byte[4096];
                SocketAddress toRemote = null;
                DatagramPacket packet = new DatagramPacket(buf, buf.length);
                in.receive(packet);
                SocketAddress from = packet.getSocketAddress();
                if ( from.equals(fromServer)) {
                    // no client yet
                    if ( fromClient == null )
                    {
                        continue;
                    }
                    fromServer(buf,packet.getLength());
                    toRemote = fromClient;
                }
                else
                {
                    // record client
                    // later on to be smart : could try to record peer id ?
                    // will add a constraint : only one auth at a time
                    if ( fromClient == null ) {
                        fromClient = from;
                    }
                    fromClient(buf,packet.getLength());
                    toRemote = fromServer;
                }
                packet = new DatagramPacket(buf, packet.getLength(), toRemote);
                in.send(packet);
            }
        }
        catch( IOException ioException)
        {
            //
            System.out.println("oops");
        }
        // socket.close();
    }

    void fromServer(byte[] buffer, int length)
    {
        try {
            // reply from server
            if (handler != null) {
                handler.fromServer(buffer, length);
            }
        }
        catch (PacketException packetException)
        {
            //
        }
    }

    void fromClient(byte[] buffer, int length)
    {
        try {
            // reply from client
            if (handler != null) {
                handler.fromClient(buffer, length);
            }
        }
        catch (PacketException packetException)
        {
            //
        }

    }


}
