package com.alterdekim.hearthhack.component;

import com.alterdekim.hearthhack.component.interfaces.OnRoomFullCallback;
import com.alterdekim.hearthhack.config.ObjectConfig;
import com.alterdekim.hearthhack.dto.RoomPlayerDTO;
import com.alterdekim.hearthhack.service.RoomService;
import com.alterdekim.hearthhack.service.UserService;
import jakarta.annotation.PostConstruct;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import java.util.List;
import java.util.Optional;
import java.util.concurrent.ConcurrentHashMap;

@Slf4j
@Component
public class GamePool {

    @Autowired
    private UserService userService;

    @Autowired
    private RoomService roomService;

    @Autowired
    private ObjectConfig config;

    private final ConcurrentHashMap<Long, GameRoom> games = new ConcurrentHashMap<>();

    @Getter
    private final ConcurrentHashMap<Long, OnRoomFullCallback> callbacks = new ConcurrentHashMap<>();

    public static final int PLAYERS_COUNT = 2; // TODO: MAKE 2 PLAYERS FOR PRODUCTION

    @Scheduled(fixedRate = 200)
    private void refreshRooms() {
        roomService.getAll()
                .forEach(r -> {
                    if( r.getPlayers().size() != PLAYERS_COUNT ) return;
                    log.info("Got room!");
                    List<RoomPlayerDTO> players = r.getPlayers();
                    log.info("Put room by id: {}", r.getId());
                    games.put(r.getId(), new GameRoom(players, userService, r.getRoomPassword(), config));
                    players.stream()
                            .filter(p -> callbacks.containsKey(p.getUserId()))
                            .forEach(p -> callbacks.get(p.getUserId()).onRoomFull());
                    roomService.removeRoom(r.getId());
                });
        // TODO: move gamemaster thread stuff here
    }

    @PostConstruct
    private void clearRooms() {
        roomService.clear();
    }

    public Optional<GameRoom> getGameRoomById(Long id) {
        return Optional.ofNullable(games.get(id));
    }
}
