package com.huangzj.base.cmd;

import com.google.protobuf.Message;
import com.google.protobuf.Parser;
import java.lang.reflect.Method;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Supplier;

/**
 * 按 protobuf 生成类做 CTS 解析 / STC Builder 创建（类比原工程 {@code ProtoMgr.decode} / {@code getStcProtoMessageByCtsNo}）。
 */
final class ProtoCommandReflect {

    private static final ConcurrentHashMap<Class<?>, Parser<?>> PARSERS = new ConcurrentHashMap<>();
    private static final ConcurrentHashMap<Class<?>, Supplier<? extends Message.Builder>> BUILDER_FACTORIES =
            new ConcurrentHashMap<>();

    private ProtoCommandReflect() {
    }

    @SuppressWarnings("unchecked")
    static <C extends Message> Parser<C> parser(Class<? extends Message> ctsClass) {
        return (Parser<C>) PARSERS.computeIfAbsent(ctsClass, ProtoCommandReflect::loadParser);
    }

    @SuppressWarnings("unchecked")
    static <B extends Message.Builder> Supplier<B> builderSupplier(Class<? extends Message> stcClass) {
        return (Supplier<B>) BUILDER_FACTORIES.computeIfAbsent(stcClass, ProtoCommandReflect::loadBuilderFactory);
    }

    private static Parser<?> loadParser(Class<?> msgClass) {
        try {
            Method m = msgClass.getMethod("parser");
            return (Parser<?>) m.invoke(null);
        } catch (ReflectiveOperationException e) {
            throw new IllegalStateException(
                    "CTS 须为 protobuf 生成类且含 public static Parser parser(): " + msgClass.getName(), e);
        }
    }

    private static Supplier<? extends Message.Builder> loadBuilderFactory(Class<?> msgClass) {
        try {
            Method m = msgClass.getMethod("newBuilder");
            Object probe = m.invoke(null);
            if (!(probe instanceof Message.Builder)) {
                throw new IllegalStateException("newBuilder 未返回 Message.Builder: " + msgClass.getName());
            }
        } catch (ReflectiveOperationException e) {
            throw new IllegalStateException(
                    "STC 须为 protobuf 生成类且含 public static Builder newBuilder(): " + msgClass.getName(), e);
        }
        return () -> {
            try {
                return (Message.Builder) msgClass.getMethod("newBuilder").invoke(null);
            } catch (ReflectiveOperationException e) {
                throw new IllegalStateException(e);
            }
        };
    }
}
