package cz.jzitnik.game.core.sound;

import java.io.IOException;
import java.lang.annotation.Annotation;
import java.util.HashMap;
import java.util.Random;
import java.util.Set;

import javax.sound.sampled.LineUnavailableException;
import javax.sound.sampled.UnsupportedAudioFileException;

import org.reflections.Reflections;

import cz.jzitnik.game.annotations.SoundRegistry;
import cz.jzitnik.game.annotations.SoundTypeSet;
import cz.jzitnik.game.config.Configuration;
import cz.jzitnik.tui.SoundPlayer;
import lombok.extern.slf4j.Slf4j;

@Slf4j
public class Sound {
    private Random random = new Random();
    private HashMap<SoundKey, SoundRegistry> map = new HashMap<>();

    public Sound() {
        register();
    }

    private void register() {
        Reflections reflections = new Reflections("cz.jzitnik.game.core.sound.registry");
        Set<Class<?>> handlerClasses = reflections.getTypesAnnotatedWith(SoundRegistry.class);

        for (Class<?> clazz : handlerClasses) {
            log.info("Loaded sound {}", clazz.getSimpleName());
            var annotation = clazz.getAnnotation(SoundRegistry.class);

            map.put(annotation.key(), annotation);
        }
    }

    public void playSound(Configuration configuration, SoundKey soundKey, Class<? extends Annotation> anot) {
        var volume = configuration.getSoundVolume();

        var annotation = map.get(soundKey);

        var resources = annotation.resourceLocation();
        var resource = resources[random.nextInt(resources.length)];

        var typeVolume = anot == null ? 100 : anot.isAnnotationPresent(SoundTypeSet.class)
                ? anot.getAnnotation(SoundTypeSet.class).value().getVolume()
                : 0;

        new Thread(() -> {
            try {
                SoundPlayer.playSound(resource, typeVolume, volume);
            } catch (LineUnavailableException | IOException | UnsupportedAudioFileException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }).start();
    }
}
