package com.cyksj.service.corp.msg;


import com.cyksj.common.task.GlobalThreadPoolTaskExecutor;
import com.cyksj.model.request.corp.CorpXmlMessage;
import com.cyksj.model.request.corp.CorpXmlOutMessage;
import com.cyksj.service.corp.CorpService;
import lombok.extern.slf4j.Slf4j;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;

/**
 * 微信消息路由器，通过代码化的配置，把来自微信的消息交给handler处理
 *
 * @author chan
 * @date 2022-03-14 下午3:42
 */
@Slf4j
public class CorpMessageRouter {

	private static final GlobalThreadPoolTaskExecutor TASK_EXECUTOR = GlobalThreadPoolTaskExecutor.getInstance();

	private final List<CorpMessageRouterRule> rules = new ArrayList<>();

	private final CorpService corpService;

	public CorpMessageRouter(CorpService wxCpService) {
		this.corpService = wxCpService;
	}

	List<CorpMessageRouterRule> getRules() {
		return this.rules;
	}

	/**
	 * 开始一个新的Route规则.
	 */
	public CorpMessageRouterRule rule() {
		return new CorpMessageRouterRule(this);
	}

	/**
	 * 处理微信消息.
	 */
	public CorpXmlOutMessage route(final CorpXmlMessage message, final Map<String, Object> context) {

		final List<CorpMessageRouterRule> matchRules = new ArrayList<>();
		// 收集匹配的规则
		for (final CorpMessageRouterRule rule : this.rules) {
			if (rule.test(message)) {
				matchRules.add(rule);
				if (!rule.isReEnter()) {
					break;
				}
			}
		}

		if (matchRules.size() == 0) {
			return null;
		}

		CorpXmlOutMessage res = null;
		final List<Future> futures = new ArrayList<>();
		for (final CorpMessageRouterRule rule : matchRules) {
			// 返回最后一个非异步的rule的执行结果
			if (rule.isAsync()) {
				futures.add(
						TASK_EXECUTOR.submit(() -> rule.service(message, context, CorpMessageRouter.this.corpService))
				);
			} else {
				res = rule.service(message, context, this.corpService);
			}
		}

		if (futures.size() > 0) {
			TASK_EXECUTOR.submit(() -> {
				for (Future future : futures) {
					try {
						future.get();
					} catch (InterruptedException e) {
						log.error("Error happened when wait task finish", e);
						Thread.currentThread().interrupt();
					} catch (ExecutionException e) {
						log.error("Error happened when wait task finish", e);
					}
				}
				return null;
			});
		}
		return res;
	}

	/**
	 * 处理微信消息.
	 */
	public CorpXmlOutMessage route(final CorpXmlMessage message) {
		return this.route(message, new HashMap<>(2));
	}

}
