package com.lona.tictactoe.web;

import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketSession;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;

public class TcpSession extends Thread {
    private final WebSocketSession session;
    private final String host;
    private final int port;
    private Socket socket;
    private volatile PrintWriter out;
    private BufferedReader in;
    private volatile boolean running = true;
    private final BlockingQueue<String> sendQueue = new LinkedBlockingQueue<>();

    public TcpSession(WebSocketSession session, String host, int port) {
        this.session = session;
        this.host = host;
        this.port = port;
    }

    @Override
    public void run() {
        try {
            System.out.println("TcpSession: Connecting to " + host + ":" + port);
            socket = new Socket(host, port);
            out = new PrintWriter(socket.getOutputStream(), true);
            in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
            System.out.println("TcpSession: Connected successfully");

            // Flush queue
            String queued;
            while ((queued = sendQueue.poll()) != null) {
                out.println(queued);
            }

            String line;
            while (running && (line = in.readLine()) != null) {
                if (session.isOpen()) {
                    session.sendMessage(new TextMessage(line));
                }
            }
        } catch (java.net.ConnectException ce) {
            System.err.println("TcpSession: Failed to connect to game server: " + ce.getMessage());
        } catch (java.net.SocketException se) {
            if (running) {
                // Only print if we didn't initiate the close
                System.err.println("TcpSession: Socket closed unexpectedly: " + se.getMessage());
                se.printStackTrace();
            }
        } catch (IOException e) {
            System.err.println("TcpSession: IO Error: " + e.getMessage());
            e.printStackTrace();
        } finally {
            close();
        }
    }

    public void send(String msg) {
        if (out != null) {
            out.println(msg);
        } else {
            sendQueue.offer(msg);
            // Double check in case we connected while queueing
            if (out != null) {
                String queued;
                while ((queued = sendQueue.poll()) != null) {
                    out.println(queued);
                }
            }
        }
    }

    public void close() {
        running = false;
        try {
            if (socket != null && !socket.isClosed())
                socket.close();
        } catch (IOException e) {
            // ignore
        }
    }
}
