package cd.casic.ci.process.engine.runContext;

import cd.casic.ci.process.engine.enums.ContextStateEnum;
import cd.casic.ci.process.engine.manager.LoggerManager;
import cd.casic.ci.process.engine.manager.RunContextManager;
import cd.casic.ci.process.enums.PiplineTriggerModeEnum;
import cd.casic.ci.process.process.dao.history.PipPipelineHisInstanceDao;
import cd.casic.ci.process.process.dataObject.base.PipBaseElement;
import cd.casic.ci.process.process.dataObject.pipeline.PipPipeline;
import cd.casic.framework.commons.exception.ServiceException;
import cd.casic.framework.commons.exception.enums.GlobalErrorCodeConstants;
import com.alibaba.fastjson.annotation.JSONField;
import com.fasterxml.jackson.annotation.JsonIgnore;
import lombok.Getter;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;

import java.time.LocalDateTime;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
@Setter
@Getter
@Slf4j
public class PipelineRunContext extends BaseRunContext{
    @JsonIgnore
    @JSONField(serialize = false)
    private PipPipelineHisInstanceDao hisInstanceDao;
    @JsonIgnore
    @JSONField(serialize = false)
    private LoggerManager loggerManager;
    private PiplineTriggerModeEnum triggerMode;
    private String userId;
    private String nickName;
    @JSONField(serialize = false)
    private RunContextManager contextManager;

    public PipelineRunContext(PipPipeline pipeline, Integer childCount) {
        this(pipeline,childCount,null,new ConcurrentHashMap<>(),new ConcurrentHashMap<>());
    }

    public PipelineRunContext(PipPipeline pipeline,Integer childCount,BaseRunContext parentContext, Map<String, Object> globalVariables, Map<String, Object> localVariables) {
        this(pipeline,childCount,parentContext,LocalDateTime.now(),pipeline.getResourceId(),pipeline.getTargetVersionId(),pipeline.getTargetType(),globalVariables,localVariables,new ConcurrentHashMap<>());
    }

    private PipelineRunContext(PipBaseElement contextDef,Integer childCount, BaseRunContext parentContext, LocalDateTime startTime, String resourceId, String targetVersionId, String targetType, Map<String, Object> globalVariables, Map<String, Object> localVariables, Map<String, BaseRunContext> childContext) {
        super(  contextDef
                ,childCount
                ,parentContext
                ,startTime
                , resourceId
                , targetVersionId
                , targetType
                , globalVariables
                , localVariables
                , childContext);
    }

    /**
     *  pipeline 底下有多个阶段，多个阶段包含多个task 不保存第二级context
     * */
    @Override
    public BaseRunContext getRunContext(String id) {
        if (this.getContextDef().getId().equals(id)) {
            return this;
        }
        Map<String, BaseRunContext> childContext = getChildContext();
        for (Map.Entry<String, BaseRunContext> entry : childContext.entrySet()) {
            BaseRunContext childRunContext = entry.getValue().getRunContext(id);
            if (childRunContext!=null) {
                return childRunContext;
            }
        }
        return null;
    }

    @Override
    public void putChildRunContext(String key, BaseRunContext context) {
        Map<String, BaseRunContext> childContext = getChildContext();
        if (context instanceof SecondStageRunContext) {
            childContext.put(key,context);
        } else {
            throw new ServiceException(GlobalErrorCodeConstants.PIPELINE_ERROR.getCode(),"不支持类型");
        }
    }
    @Override
    public void changeContextState(ContextStateEnum stateEnum){
        ContextStateEnum curr = ContextStateEnum.getByCode(getState().get());
        if (ContextStateEnum.canGoto(curr,stateEnum)) {
            state.compareAndExchange(curr.getCode(),stateEnum.getCode());
            if (ContextStateEnum.HAPPY_ENDING.equals(stateEnum)
                    ||ContextStateEnum.BAD_ENDING.equals(stateEnum)
                    ||ContextStateEnum.SKIP_TO.equals(stateEnum)) {
                this.endTime=LocalDateTime.now();
                if (!curr.equals(ContextStateEnum.HAPPY_ENDING)) {
                    // 入库保存
                    contextManager.toHistory(getContextDef().getId());
                }

            }
        } else {
            log.error("非法状态扭转直接忽略,{},{}",curr,stateEnum);
        }
    }

}
