package io.wdd.func.auto.service;

import io.wdd.func.auto.beans.ImageSyncContext;
import io.wdd.pusher.MessagePusher;
import io.wdd.pusher.beans.ImageSyncMessage;
import io.wdd.pusher.beans.NtfyReceiveMessage;
import io.wdd.pusher.beans.PushMessageType;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;

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

import static io.wdd.func.auto.beans.ImageFunctionEnum.*;
import static io.wdd.func.auto.service.FuncServiceImpl.JudgeSyncBaseCommandResult;

@Service
@Slf4j
public class ImageFuncScheduler {

    public static final String CmiiHarborHostPrefix = "harbor.cdcyy.com.cn/cmii/";
    @Resource
    FuncService funcService;

    @Resource
    MessagePusher messagePusher;

    public boolean runProcedure(ImageSyncContext imageSyncContext) {

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


        // during run
        doRunProcedure(imageSyncContext);


        // after run
        afterRunProcedure(imageSyncContext);


        return true;
    }

    private void beforeRunProcedure(ImageSyncContext imageSyncContext) {

        // build args

        // imageFullName gzipFolderPrefix gzipFileName ossUrlPrefix proxyUrl targetHarborHost namespace targetImageFullName
        ArrayList<String> arrayList = new ArrayList<>();
        arrayList.add(""); //imageFullName
        arrayList.add("/var/lib/docker/octopus_image/"); //gzipFolderPrefix
        arrayList.add(""); //gzipFileName
        arrayList.add("https://oss.demo.uavcmlc.com/cmlc-installation/tmp/");//ossUrlPrefix
        arrayList.add("");//proxyUrl
        arrayList.add(imageSyncContext.getProjectMasterNode().getServerIpInV4());//targetHarborHost
        arrayList.add(imageSyncContext.getProjectInfoPO().getProjectNamespace());//namespace
        arrayList.add("");//targetImageFullName

        imageSyncContext.setImageSyncFuncArgs(arrayList);

        // 构建消息发送结构体
        imageSyncContext.setImageSyncMessage(new ImageSyncMessage());

        log.debug("beforeRunProcedure complete!");
    }

    private void afterRunProcedure(ImageSyncContext imageSyncContext) {

        // message-pusher
        ImageSyncMessage imageSyncMessage = imageSyncContext.getImageSyncMessage();
        NtfyReceiveMessage receiveMessage = messagePusher.Send(imageSyncMessage, PushMessageType.IMAGE_SYNC);

        log.info("Image sync message push result => {}", receiveMessage.getRaw());

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

    private void doRunProcedure(ImageSyncContext imageSyncContext) {

        List<String> realFullNameList = null;
        ArrayList<String> cmiiAppNameTagList = imageSyncContext.getCmiiAppNameTagList();
        ArrayList<String> imageFullNameList = imageSyncContext.getImageFullNameList();

        if (CollectionUtils.isNotEmpty(cmiiAppNameTagList)) {
            realFullNameList = cmiiAppNameTagList.stream().map(CmiiHarborHostPrefix::concat).collect(Collectors.toList());
        }


        if (CollectionUtils.isNotEmpty(imageFullNameList)) {
            if (CollectionUtils.isEmpty(realFullNameList)) {
                //
                realFullNameList = imageFullNameList;
            } else {
                // cmii app tag name not null && imageFullNameList not nuill
                realFullNameList.addAll(imageFullNameList);
            }
        }

        if (realFullNameList == null) {
            log.info("Image Sync image list is null, return !");
            return;
        }

        log.info("prepare to update {} {} \n{}", imageSyncContext.getProjectInfoPO().getProjectNamespace(), imageSyncContext.getProjectMasterNode().getServerIpInV4(), realFullNameList);


        String innerWorkerAgentName = imageSyncContext.getInnerWorkerAgentName();
        Assert.notNull(innerWorkerAgentName, "inner worker agent name cant not be null !");

        ArrayList<String> imageSyncFuncArgs = imageSyncContext.getImageSyncFuncArgs();

        String outsideAgentTopicName = imageSyncContext.getProjectMasterNode().getAgentTopicName();

        // 设置消息体
        ImageSyncMessage imageSyncMessage = imageSyncContext.getImageSyncMessage();
        imageSyncMessage.setIsSyncFinished(Boolean.FALSE);
        imageSyncMessage.setProjectNameSpace(imageSyncContext.getProjectInfoPO().getProjectNamespace());
        imageSyncMessage.setProjectName(imageSyncContext.getProjectInfoPO().getProjectName());
        imageSyncMessage.setInnerWorkTopicName(imageSyncContext.getInnerWorkerAgentName());
        imageSyncMessage.setProjectMasterTopicName(imageSyncContext.getProjectMasterNode().getAgentTopicName());
        imageSyncMessage.setProjectMasterIP(imageSyncContext.getProjectMasterNode().getServerIpInV4());

        //
        List<String> resultLog;
        for (String imageFullName : realFullNameList) {
            imageSyncMessage.setImageFullName(imageFullName);

            // innerWorkerAgent
            imageSyncFuncArgs.set(0, imageFullName);
            resultLog = funcService.callImageFuncService(innerWorkerAgentName, DOWNLOAD_DOCKER_IMAGE, imageSyncFuncArgs);
            if (!JudgeSyncBaseCommandResult(resultLog)) {
                imageSyncMessage.setCurrentProcedure(DOWNLOAD_DOCKER_IMAGE.getFuncName());
                return;
            }
            resultLog = funcService.callImageFuncService(innerWorkerAgentName, COMPRESS_IMAGE_TO_GZIP, imageSyncFuncArgs);
            if (!JudgeSyncBaseCommandResult(resultLog)) {
                imageSyncMessage.setCurrentProcedure(COMPRESS_IMAGE_TO_GZIP.getFuncName());
                return;
            }
            String gzipFileName = resultLog.get(0);
            Assert.notNull(gzipFileName, "COMPRESS_IMAGE_TO_GZIP return gzip file name is null !");
            imageSyncFuncArgs.set(2, gzipFileName);
            resultLog = funcService.callImageFuncService(innerWorkerAgentName, UPLOAD_GZIP_TO_OSS, imageSyncFuncArgs);
            if (!JudgeSyncBaseCommandResult(resultLog)) {
                imageSyncMessage.setCurrentProcedure(UPLOAD_GZIP_TO_OSS.getFuncName());
                return;
            }

            log.info("Image Sync Half Complete ! Gzip file name => {}", gzipFileName);
            if (imageSyncContext.getDownloadAndCompressOnly()) {
                log.info("Image Sync download  only !");
                imageSyncMessage.setCurrentProcedure(FINISHED.getFuncName());
                imageSyncMessage.setIsSyncFinished(true);
                return;
            }

            // outside agent
            resultLog = funcService.callImageFuncService(outsideAgentTopicName, DOWNLOAD_GZIP_IMAGE_FILE, imageSyncFuncArgs);
            if (!JudgeSyncBaseCommandResult(resultLog)) {
                imageSyncMessage.setCurrentProcedure(DOWNLOAD_GZIP_IMAGE_FILE.getFuncName());
                return;
            }
            resultLog = funcService.callImageFuncService(outsideAgentTopicName, LOAD_DOCKER_IMAGE_FROM_GZIP, imageSyncFuncArgs);
            if (!JudgeSyncBaseCommandResult(resultLog)) {
                imageSyncMessage.setCurrentProcedure(LOAD_DOCKER_IMAGE_FROM_GZIP.getFuncName());
                return;
            }
            resultLog = funcService.callImageFuncService(outsideAgentTopicName, PUSH_IMAGE_TO_TARGET_HARBOR, imageSyncFuncArgs);
            if (!JudgeSyncBaseCommandResult(resultLog)) {
                imageSyncMessage.setCurrentProcedure(PUSH_IMAGE_TO_TARGET_HARBOR.getFuncName());
                return;
            }
            resultLog = funcService.callImageFuncService(outsideAgentTopicName, UPDATE_IMAGE_TAG, imageSyncFuncArgs);
            if (!JudgeSyncBaseCommandResult(resultLog)) {
                imageSyncMessage.setCurrentProcedure(UPDATE_IMAGE_TAG.getFuncName());
                return;
            }

            imageSyncMessage.setCurrentProcedure(FINISHED.getFuncName());
            imageSyncMessage.setIsSyncFinished(true);
        }

    }
}
