package cz.jzitnik.game.handlers.place;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Set;

import cz.jzitnik.game.annotations.*;
import lombok.extern.slf4j.Slf4j;

import org.reflections.Reflections;

@Slf4j
public class PlaceHandler {
    private final HashMap<String, CustomPlaceHandler> placeHandlerList = new HashMap<>();
    private final CustomPlaceHandler defaultPlaceHandler = new DefaultPlaceHandler();
    private final List<String> placeOnSolid = new ArrayList<>();

    public boolean isPlaceOnSolid(String id) {
        return placeOnSolid.contains(id);
    }

    public boolean contains(String itemId) {
        return placeHandlerList.containsKey(itemId);
    }

    public CustomPlaceHandler get(String itemId) {
        if (!contains(itemId)) {
            return defaultPlaceHandler;
        }

        var placeHandler = placeHandlerList.get(itemId);

        log.debug("Using {} to mine/place a block", placeHandler.getClass().getSimpleName());
        return placeHandler;
    }

    public PlaceHandler() {
        registerHandlers();
    }

    private void registerHandlers() {
        Reflections reflections = new Reflections("cz.jzitnik.game.handlers.place.handlers");
        Set<Class<?>> handlerClasses = reflections
                .getTypesAnnotatedWith(cz.jzitnik.game.annotations.PlaceHandler.class);

        for (Class<?> clazz : handlerClasses) {
            if (CustomPlaceHandler.class.isAssignableFrom(clazz)) {
                try {
                    CustomPlaceHandler handlerInstance = (CustomPlaceHandler) clazz.getDeclaredConstructor()
                            .newInstance();
                    cz.jzitnik.game.annotations.PlaceHandler annotation = clazz
                            .getAnnotation(cz.jzitnik.game.annotations.PlaceHandler.class);
                    placeHandlerList.put(annotation.value(), handlerInstance);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }

        Reflections reflections2 = new Reflections("cz.jzitnik.game.entities.items.registry.blocks");
        Set<Class<?>> blocks = reflections2
                .getTypesAnnotatedWith(BlockRegistry.class);

        for (Class<?> clazz : blocks) {
            var annotation = clazz.getAnnotation(BlockRegistry.class);
            var id = annotation.value();
            if (clazz.isAnnotationPresent(PlaceOnSolid.class) || clazz.isAnnotationPresent(ResetDataOnMine.class)
                    || clazz.isAnnotationPresent(BlockDropPercentage.class)
                    || clazz.isAnnotationPresent(CustomDrops.class) || clazz.isAnnotationPresent(CustomDrop.class)
                    || clazz.isAnnotationPresent(TwoblockBlock.class) || clazz.isAnnotationPresent(ResetSpriteStateOnMine.class)) {
                placeHandlerList.put(id, new CustomAnnotationHandler(clazz));
            }

            if (clazz.isAnnotationPresent(PlaceOnSolid.class)
                    || clazz.isAnnotationPresent(PlaceOnSolidNoHandler.class)) {
                placeOnSolid.add(id);
            }
        }
    }
}
