package com.alterdekim.hearthhack.component;


import com.alterdekim.hearthhack.component.processor.Processor;
import com.alterdekim.hearthhack.config.ObjectConfig;
import com.alterdekim.hearthhack.config.ServerConfig;
import com.alterdekim.hearthhack.reflect.ReflectionLoader;
import com.alterdekim.hearthhack.service.UserService;
import com.alterdekim.hearthhack.util.Util;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import javax.net.ssl.SSLServerSocket;
import javax.net.ssl.SSLSocket;
import java.io.IOException;
import java.util.LinkedList;
import java.util.List;

@Slf4j
@Component
public class TcpServer extends ReflectionLoader<Processor> {

    private int socketPort;

    private SSLServerSocket serverSocket;
    private List<TcpConnection> connections;

    @Autowired
    private ObjectConfig dbfConfig;

    @Autowired
    private ServerConfig serverConfig;

    @Autowired
    private UserService userService;

    @Scheduled(fixedDelay = 5000)
    private void start() {
        try {
            this.socketPort = serverConfig.getBnetPort();
            this.initReflect(Processor.class);
            if( serverSocket != null && !serverSocket.isClosed() ) {
                serverSocket.close();
                serverSocket = null;
            }
            this.connections = new LinkedList<>();
            this.serverSocket = (SSLServerSocket) Util.getSocketFactory(
                    "test.com.crt", // "test.com.crt"
                    "test.com.crt", // "test.com.crt"
                    "test.com.key", // "test.com.key"
                    ""
            ).createServerSocket(this.socketPort, 15);

            while(true) {
                SSLSocket s = (SSLSocket) serverSocket.accept();
                TcpConnection c = new TcpConnection(s, this.getParsers(), dbfConfig, userService);
                connections.add(c);
                c.start();
                log.info("New Connection Established From {}", s.getInetAddress().toString());
            }
        } catch (IOException e) {
            log.error(e.getMessage());
        }
    }

    public void stopListening() {
        connections.forEach(TcpConnection::stopListeningAndDisconnect);
        try {
            serverSocket.close();
        } catch (IOException e) {
            log.error(e.getMessage());
        }
    }

    public void removeConnection(TcpConnection c) {
        connections.remove(c);
    }
}
