package com.elab.spring.design.group;

import com.elab.spring.utils.ThreadProcessUtils;
import org.springframework.beans.factory.annotation.Autowired;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Supplier;

public abstract class AbstractInvocationProcess<T, R extends GroupResult> {

    @Autowired
    private GroupInvocationManager groupInvocationManager;

    protected boolean preHandler(T req) {
        return true;
    }

    public abstract String groupName();

    public abstract R postHandler(T req, Map<String, Object> res);

    public R invoke(T req) throws Exception {

        String groupName = groupName();

        if (!this.preHandler(req)) {
            return null;
        }

        List<GroupRouteInvocation> invocationList = groupInvocationManager.getInvocationList(groupName);

        Map<String, Supplier<Object>> threadResultMap = new HashMap<>();

        for (int i = 0; i < invocationList.size(); i++) {
            GroupRouteInvocation groupRouteInvocation = invocationList.get(i);
            String unionKey = groupRouteInvocation.unionKey();
            if (groupRouteInvocation instanceof SubscribeInvocation) {
                SubscribeInvocation subscribeInvocation = (SubscribeInvocation)groupRouteInvocation;

                if (!subscribeInvocation.preHandler(req)) {
                    continue;
                }
            }

            threadResultMap.put(unionKey, () -> {
                return groupRouteInvocation.invoke(req);
            });

        }

        Map<String, Object> resultMap = ThreadProcessUtils.supplyAsyncByMap(threadResultMap);

        return postHandler(req, resultMap);
    }

}


