package com.alterdekim.game.component;

import com.alterdekim.game.component.rtmp.ConnectedProcessor;
import com.alterdekim.game.component.rtmp.ConnectionProcessor;
import com.alterdekim.game.component.rtmp.ConnectionState;
import com.alterdekim.game.component.rtmp.HandshakeProcessor;
import lombok.Getter;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;

import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

@Slf4j
public class RTMPListener extends Thread {

    private Socket sock;

    private RTMPServer parent;

    @Getter
    @Setter
    private Integer uid;
    private InputStream in;
    private OutputStream out;

    private ConnectionState connectionState;

    private final Map<ConnectionState, ConnectionProcessor> connectionProcessors = new ConcurrentHashMap<>();

    public RTMPListener(Socket sock, RTMPServer parent, Integer uid, GameServer gameServer) {
        try {
            this.uid = uid;
            this.parent = parent;
            this.sock = sock;
            this.in = sock.getInputStream();
            this.out = sock.getOutputStream();
            this.connectionState = ConnectionState.HANDSHAKE;
            this.connectionProcessors.put(ConnectionState.HANDSHAKE, new HandshakeProcessor(this.in, this.out, this.sock));
            this.connectionProcessors.put(ConnectionState.CONNECTED, new ConnectedProcessor(this.in, this.out, this.sock, gameServer));
        } catch( Exception e ) {
            log.error("RTMPListener error", e);
        }
    }

    @Override
    public void run() {
        try {
            while(!sock.isClosed()) {
                this.connectionState = this.connectionProcessors.get(this.connectionState).process();
            }
            this.parent.close(this.getUid());
        } catch( Exception e ) {
            log.error("RTMPListener.run() error", e);
        } finally {
            try {
                sock.close();
            } catch (Exception e) {
                log.error("RTMPListener.run() error", e);
            }
        }
    }
}
