package com.tsi.sig.server.websocket;

import com.tsi.sig.server.config.KafkaConsumerConfig;
import com.tsi.sig.server.websocket.kafka.AllTopicConsumerThread;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.socket.CloseStatus;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketSession;
import org.springframework.web.socket.handler.TextWebSocketHandler;

import java.util.ArrayList;
import java.util.List;

@Slf4j
@Controller
@RequestMapping("/allTopic.do")
public class AllTopicCvimHandler extends TextWebSocketHandler {

    private final KafkaConsumerConfig kafkaConsumerConfig;

    private List<WebSocketSession> sessionList = new ArrayList<WebSocketSession>();
    private AllTopicConsumerThread consumerThread = null;
    private Thread thread;

    public AllTopicCvimHandler(com.tsi.sig.server.config.KafkaConsumerConfig kafkaConsumerConfig) {
        this.kafkaConsumerConfig = kafkaConsumerConfig;
        this.consumerThread = new AllTopicConsumerThread(this, this.kafkaConsumerConfig);
    }

    @Override
    public void afterConnectionEstablished(WebSocketSession session) throws Exception {
        // 클라이언트가 연결되었을때 실행
        try {
            this.sessionList.add(session);
            this.consumerThread.addSession(session);
        } catch (Exception e) {
        }
        log.info("AllTopicCvimHandler, WebSocket [in]  RemoteAddress: " + session.getRemoteAddress() + ",  Uri" + session.getUri() + ", UUID" + session.getId());
    }

    //클라이언트가 웹소켓 서버로 메시지를 전송했을 때 실행
    @Override
    protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {
    }

    //클라이언트 연결을 끊었을 때 실행
    @Override
    public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception {
        try {
            this.consumerThread.removeSession(session);
            this.sessionList.remove(session);
        } catch (Exception e) {
        }
        log.info("AllTopicCvimHandler, WebSocket [out]  RemoteAddress: " + session.getRemoteAddress() + ",  Uri: " + session.getUri() + ", UUID: " + session.getId());
    }

    public void sendMessage(WebSocketSession session, TextMessage message) {

        if (session != null && session.isOpen()) {
            synchronized (session) {
                try {
                    session.sendMessage(message);
                } catch (Exception e) {
                    log.error("AllTopicCvimHandler, sendMessage: session: {}, {}", session, e.getMessage());
                }
            }
        }
    }

    public void shutdown() {
        if (!this.consumerThread.getStopFlag().get()) {
            this.consumerThread.shutdown();
        }
    }

    public void start() throws Exception {
        if (this.consumerThread.getStopFlag().get()) {
            log.info("AllTopicCvimHandler, Start by stopFlag. {}", this.consumerThread);
            this.thread = null;
            this.consumerThread = null;
            this.consumerThread = new AllTopicConsumerThread(this, this.kafkaConsumerConfig);
            this.thread = new Thread(this.consumerThread);
            this.thread.setUncaughtExceptionHandler(
                    new Thread.UncaughtExceptionHandler() {
                        @Override
                        public void uncaughtException(Thread th, Throwable ex) {
                            log.error("Uncaught exception: {}", ex.getMessage());
                            shutdown();
                        }
                    }
            );
            this.thread.start();
        }
    }

    public void stop() {
        try {
            if (!this.consumerThread.getStopFlag().get()) {
                this.consumerThread.stop();
            }
        }
        catch (Exception e) {
        }
    }
}
