package io.wdd.func.auto.service;

import io.wdd.func.auto.beans.BaseFunctionEnum;
import io.wdd.func.auto.beans.ProjectDeployContext;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

@Service
@Slf4j
public class BaseFuncScheduler {

    @Resource
    FuncService funcService;

    public boolean runProcedure(ProjectDeployContext projectDeployContext) {

        // before run
        // check base requirement
        beforeRunProcedure(projectDeployContext);


        // during run
        doRunProcedure(projectDeployContext);


        // after run
        afterRunProcedure();


        return true;
    }

    private void afterRunProcedure() {

        // 检查是否安装完成, 对安装环境进行判定
        log.debug("afterRunProcedure complete!");
    }

    private void doRunProcedure(ProjectDeployContext projectDeployContext) {


        if (!MasterNodeBaseProcedure(projectDeployContext)) {
            log.error("Master 初始化过程错误! 即将终止!");
        }


        if (!CollectionUtils.isEmpty(projectDeployContext
                                             .getAgentNodeList())) {

            List<String> agentTopicNameList = projectDeployContext
                    .getAgentNodeList()
                    .stream()
                    .map(agentNode -> agentNode.getTopicName())
                    .collect(Collectors.toList());

            if (!AgentNodeProcedure(agentTopicNameList)) {
                log.error("Agent 初始化过程错误! 即将终止!");
            }
        }

        log.info("初始化过程完成!");
    }


    private void beforeRunProcedure(ProjectDeployContext projectDeployContext) {

        // 检查是否符合规定

        // 检查每一个Agent是否能够连通,调用命令返回结果

        // 打印施工信息

        log.debug("beforeRunProcedure complete!");

    }

    private boolean MasterNodeBaseProcedure(ProjectDeployContext projectDeployContext) {

        // 执行 基础功能施工的内容
        String masterTopicName = projectDeployContext
                .getMasterNode()
                .getTopicName();

        // base func args
        ArrayList<String> baseFuncArgList = new ArrayList<>();
        baseFuncArgList.add(projectDeployContext
                                    .getMasterNode()
                                    .getServerIpInV4());


        List<BaseFunctionEnum> masterNodeProcedureList = List.of(
                BaseFunctionEnum.DISABLE_SWAP,
                BaseFunctionEnum.SHUTDOWN_FIREWALL,
                BaseFunctionEnum.DISABLE_SELINUX
        );


        for (BaseFunctionEnum procedure : masterNodeProcedureList) {

            //  add op name
            baseFuncArgList.add(
                    0,
                    procedure.getFuncName()
            );

            if (!funcService.callBaseFuncAndJudge(
                    masterTopicName,
                    procedure,
                    baseFuncArgList,
                    false
            )) {

                log.error(
                        "MasterNode初始化错误 => {}",
                        procedure
                );

                return false;
            }


            // remove first args
            baseFuncArgList.remove(0);

        }

        List<BaseFunctionEnum> masterNodeDurationTaskList = List.of(
                BaseFunctionEnum.INSTALL_DOCKER,
                BaseFunctionEnum.INSTALL_DOCKER_COMPOSE,
                BaseFunctionEnum.MODIFY_DOCKER_CONFIG
//                BaseFunctionEnum.INSTALL_HARBOR
        );

        for (BaseFunctionEnum durationBaseFunc : masterNodeDurationTaskList) {

            //  add op name
            baseFuncArgList.add(
                    0,
                    durationBaseFunc.getFuncName()
            );

            if (!funcService.callBaseFuncAndJudge(
                    masterTopicName,
                    durationBaseFunc,
                    baseFuncArgList,
                    true
            )) {
                log.error(
                        "Master Duration Task Failed ! => {}",
                        durationBaseFunc
                );
                return false;
            }

            // remove
            baseFuncArgList.remove(0);
        }

        return true;
    }


    private boolean AgentNodeProcedure(List<String> agentTopicNameList) {

        return true;
    }

}
