package com.bocloud.ims.service.internal.worker;

import com.bocloud.common.enums.BoCloudMethod;
import com.bocloud.common.enums.BoCloudService;
import com.bocloud.common.enums.PostDataFormat;
import com.bocloud.common.model.BocloudResult;
import com.bocloud.common.utils.MapTools;
import com.bocloud.service.http.core.ServiceFactory;
import com.bocloud.service.http.model.RemoteService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.amqp.rabbit.core.RabbitAdmin;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Component;

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

/**
 * 请求worker
 *
 * @author lkx007
 */
@Component
public class RequestWorker {
    private static final String JOB_SUBMIT_URL = "/api/worker/v1/job/submit";
    private static final Map<String, Object> HEADERS = MapTools.simpleMap("Content-Type", "application/json");
    private ServiceFactory serviceFactory;
    private RabbitAdmin rabbitAdmin;
    private Logger logger = LoggerFactory.getLogger(this.getClass());
    private List<WorkerHost> targets;
    private List<Group> groups;
    private Integer timeout;
    private Module<?> module;
    private ThreadPoolTaskExecutor taskExecutor;
    /**
     * http://192.168.2.86:18089
     */
    private String service;

    public RequestWorker() {
        super();
    }

    public RequestWorker(List<WorkerHost> targets, Module<?> module, ServiceFactory serviceFactory,
                         RabbitAdmin rabbitAdmin, ThreadPoolTaskExecutor taskExecutor) {
        super();
        this.timeout = 1000 * 30;
        this.targets = targets;
        this.module = module;
        this.serviceFactory = serviceFactory;
        this.rabbitAdmin = rabbitAdmin;
        this.taskExecutor = taskExecutor;
    }

    public RequestWorker(List<WorkerHost> targets, Module<?> module, List<Group> groups, ServiceFactory serviceFactory,
                         RabbitAdmin rabbitAdmin, ThreadPoolTaskExecutor taskExecutor) {
        super();
        this.timeout = 1000 * 30;
        this.targets = targets;
        this.module = module;
        this.groups = groups;
        this.serviceFactory = serviceFactory;
        this.rabbitAdmin = rabbitAdmin;
        this.taskExecutor = taskExecutor;
    }

    public void setService(String service) {
        this.service = service;
    }

    public BocloudResult invoke() {
        try {
        	Map<String, Object> paramsMap = new HashMap<>();
        	paramsMap.put("targets", targets);
        	paramsMap.put("groups", groups);
        	paramsMap.put("module", module);
        	paramsMap.put("sync", false);
            RemoteService remoteService = serviceFactory.build(BoCloudService.WORKER, JOB_SUBMIT_URL,
                    BoCloudMethod.OPERATE, HEADERS, paramsMap);
            if (!remoteService.isExist()) {
                return new BocloudResult<>(false, "Remote Service [{}] does not exist!", BoCloudService.WORKER.getNode());
            }
            remoteService.setDataFormat(PostDataFormat.RAW);
            // for debug
            if (service != null) {
                remoteService.setUrl(service + JOB_SUBMIT_URL);
            }
            RemoteWorker remoteWorker = new RemoteWorker(remoteService, rabbitAdmin, timeout, null, false);
            Future<BocloudResult> workerTask = taskExecutor.submit(remoteWorker);
            return workerTask.get();
        } catch (Exception e) {
            logger.error("async request worker invoke exception:", e);
            return new BocloudResult(false, "异步获取worker结果异常");
        }
    }

    public BocloudResult invoke(String queue) {
        try {
        	Map<String, Object> paramsMap = new HashMap<>();
        	paramsMap.put("targets", targets);
        	paramsMap.put("groups", groups);
        	paramsMap.put("module", module);
        	paramsMap.put("sync", true);
            RemoteService remoteService = serviceFactory.build(BoCloudService.WORKER, JOB_SUBMIT_URL,
                    BoCloudMethod.OPERATE, HEADERS, paramsMap);
            remoteService.setDataFormat(PostDataFormat.RAW);
            // for debug
            if (service != null) {
                remoteService.setUrl(service + JOB_SUBMIT_URL);
            }
            RemoteWorker remoteWorker = new RemoteWorker(remoteService, rabbitAdmin, timeout, queue, true);
            Future<BocloudResult> workerTask = taskExecutor.submit(remoteWorker);
            return workerTask.get();
        } catch (Exception e) {
            logger.error("sync request worker invoke exception:", e);
            return new BocloudResult(false, "同步请求worker异常");
        }
    }
}
