package com.lingniu.ingest.core.dispatcher;

import com.lingniu.ingest.api.ProtocolId;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * Handler 注册中心。按 {@code (ProtocolId, command)} 索引，O(1) 查找；同 key 可注册多个 Handler，由
 * {@link HandlerDefinition#matches} 进一步精确匹配 {@code infoType}。
 */
public final class HandlerRegistry {

    private final Map<RoutingKey, List<HandlerDefinition>> byRoute = new ConcurrentHashMap<>();
    private final List<HandlerDefinition> wildcardHandlers = Collections.synchronizedList(new ArrayList<>());

    public void register(HandlerDefinition def) {
        if (def.command() == 0) {
            wildcardHandlers.add(def);
            return;
        }
        byRoute.computeIfAbsent(new RoutingKey(def.protocol(), def.command()),
                k -> Collections.synchronizedList(new ArrayList<>())).add(def);
    }

    public List<HandlerDefinition> resolve(ProtocolId protocol, int command, int infoType) {
        List<HandlerDefinition> exact = byRoute.get(new RoutingKey(protocol, command));
        List<HandlerDefinition> result = new ArrayList<>();
        if (exact != null) {
            for (HandlerDefinition d : exact) {
                if (d.matches(protocol, command, infoType)) result.add(d);
            }
        }
        if (!result.isEmpty()) {
            return result;
        }
        for (HandlerDefinition d : wildcardHandlers) {
            if (d.matches(protocol, command, infoType)) result.add(d);
        }
        return result;
    }

    public int size() {
        return byRoute.values().stream().mapToInt(List::size).sum() + wildcardHandlers.size();
    }

    private record RoutingKey(ProtocolId protocol, int command) {}
}
