package com.kospo.talk.controller;

import com.kospo.talk.model.User;
import com.kospo.talk.payload.*;
import io.swagger.v3.oas.annotations.Hidden;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.messaging.handler.annotation.DestinationVariable;
import org.springframework.messaging.handler.annotation.MessageMapping;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Controller;
import org.springframework.util.CollectionUtils;

import java.io.IOException;
import java.net.SocketException;
import java.security.Principal;
import java.util.*;

@Controller
@Hidden
@RequiredArgsConstructor
@Slf4j
public class HubController {
    @Value("${rabbitmq.hub.exchange}")
    private String hubExchange;
    @Value("${rabbitmq.hub.route}")
    private String hubRoute;
    private final RabbitTemplate hubTemplate;
    private Map<String, List<String>> connectList = new HashMap<>();


    @MessageMapping("hub.start.{tabId}")
    public void start(TalkDto talkDto, @DestinationVariable String tabId) throws IOException {
        try {
            List<String> connect = connectList.get(talkDto.getInsSabun());
            if(connect == null) {
                connect = new ArrayList<>();
            } else {
                connect = new ArrayList<>(connect);
            }

            if(!connect.contains(tabId)) {
                connect.add(tabId);
                connectList.put(talkDto.getInsSabun(), connect);
            }

        } catch(Exception e) {}
    }

    @MessageMapping("hub.close.{tabId}")
    public void close(TalkDto talkDto) throws IOException {
//        System.out.println("hub.close start : "  + connectList);
//        System.out.println("hub.close start : "  + talkDto.toString());
        try {
            if(!CollectionUtils.isEmpty(connectList)) {
                List<String> connect = connectList.get(talkDto.getChannelSabun());
                connect = new ArrayList<>(connect);
                connect.remove(talkDto.getTabId());
                connectList.put(talkDto.getChannelSabun(), connect);

//                System.out.println("hub.close end : "  + connectList);
            }
        } catch(Exception e) {}
    }

    @MessageMapping("hub.kill")
    public void kill(TalkDto talkDto) throws IOException {
//        System.out.println("hub.close start : "  + connectList);
//        System.out.println("hub.close start : "  + talkDto.toString());
        try {
            connectList.put(talkDto.getChannelSabun(), new LinkedList<>());
        } catch(Exception e) {}
    }

    @MessageMapping("hub.send.otherInit")
    public void channelOtherInit(TalkDto talkDto) {
        try {
            if(!CollectionUtils.isEmpty(connectList)) {
                connectList.get(talkDto.getInsSabun()).stream().forEach((conn) -> hubTemplate.convertAndSend(hubExchange, hubRoute + conn, talkDto));
            }
        } catch(Exception e) {}
    }

    @MessageMapping("hub.send.setMaster")
    public void channelSetMaster(TalkDto talkDto) throws IOException {
        try {
            talkDto.setType("SEND_SET_MASTER");
            if(!CollectionUtils.isEmpty(connectList)) {
                connectList.get(talkDto.getInsSabun()).stream().forEach((conn) -> hubTemplate.convertAndSend(hubExchange, hubRoute + conn, talkDto));
            }
        } catch(Exception e) {}
    }

    @MessageMapping("hub.otherInit")
    public void otherInit(OtherDto otherDto) throws IOException {
        try {
            if(!CollectionUtils.isEmpty(connectList)) {
                connectList.get(otherDto.getInsSabun()).stream().forEach((conn) -> hubTemplate.convertAndSend(hubExchange, hubRoute + conn, otherDto));
            }
        } catch(Exception e) {}
    }

    @MessageMapping("hub.talk.message")
    public void userMessage(TalkDto talkDto) throws IOException {
        try {
            if(!CollectionUtils.isEmpty(connectList)) {
                connectList.get(talkDto.getChannelSabun()).stream().forEach((conn) -> hubTemplate.convertAndSend(hubExchange, hubRoute + conn, talkDto));
            }
        } catch(Exception e) {}
    }

    @MessageMapping("hub.file.message")
    public void fileMessage(MessageDto messageDto) throws IOException {
        try {
            if(!CollectionUtils.isEmpty(connectList)) {
                connectList.get(messageDto.getChannelSabun()).stream().forEach((conn) -> hubTemplate.convertAndSend(hubExchange, hubRoute + conn, messageDto));
            }
        } catch(Exception e) {}
    }

    @MessageMapping("hub.work")
    public void work(TalkNotStartDto talkNotStartDto) {
        try {
            if(!CollectionUtils.isEmpty(connectList)) {
                connectList.get(talkNotStartDto.getChannelSabun()).stream().forEach((conn) -> hubTemplate.convertAndSend(hubExchange, hubRoute + conn, talkNotStartDto));
            }
        } catch(Exception e) {}
    }

    @MessageMapping("hub.online")
    public void online(OnlineDto onlineDto) throws IOException {
        try {
//            System.out.println(onlineDto.getType());
            if(!CollectionUtils.isEmpty(connectList)) {
                connectList.get(onlineDto.getChannelSabun()).stream().forEach((conn) -> hubTemplate.convertAndSend(hubExchange, hubRoute + conn, onlineDto));
            }
        } catch(Exception e) {}
    }


    @MessageMapping("hub.checker.{tabId}")
    public void alive(@DestinationVariable String tabId, Principal principal) {
        MessageDto messageDto = new MessageDto();
        messageDto.setType("CHECKER");
        hubTemplate.convertAndSend(hubExchange, hubRoute + tabId, messageDto);
    }

}
