package com.friday.distributor.bean;

import com.alibaba.fastjson.annotation.JSONField;
import com.friday.blank.api.dto.taskType.TaskTypeDetailDto;
import com.friday.blank.api.dto.taskType.TaskTypeMachineDto;
import com.friday.distributor.constant.Events;
import com.friday.distributor.constant.States;
import com.friday.operation.api.distributor.bean.BaseJob;
import com.friday.operation.api.distributor.dto.StandardJobInput;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import org.springframework.statemachine.StateMachine;

import java.time.LocalDateTime;
import java.util.List;
import java.util.Objects;

/**
 * @Author YaoYao
 * @Date Created In 19:29 2022/2/23
 * @Description Job类
 * @Modified By
 */
@EqualsAndHashCode(callSuper = true)
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Job extends BaseJob {
    //TAIE租户Key
    private String taieTenant;
    //任务业务类型
    private String taskType;
    //任务类型
    private String bizType;
    //任务ID
    private String taskId;
    //invoke表Id
    private Integer invokeId;
    //队列key
    private String queueKey;
    //子任务描述
    private String description;
    //子任务入参
    private StandardJobInput jobInput;
    //子任务出参
    private String jobOutput;
    //重试次数
    private int retryTime;
    //Job实际运行Id(OC.jobId/AI.fileId/Executor.threadId)
    private String execJobId;
    //子任务状态
    private String state;
    //执行失败原因
    private String failMsg;
    //备注信息
    private String remark;
    //创建时间
    private LocalDateTime createTime;
    //启动时间
    private LocalDateTime jobStartTime;
    //结束时间
    private LocalDateTime jobEndTime;
    //饥饿时间 min
    private Integer starve;
    //是否正在请求资源启动中
    private boolean scheduling;
    //指定启动的robot
    private List<TaskTypeMachineDto> givenRobots;
    //实际运行的robot
    private TaskTypeMachineDto execRobot;
    //管理端任务运行参数
    private TaskTypeDetailDto taskExecConfig;
    //状态机
    @JSONField(serialize = false)
    private StateMachine<States.JobState, Events.JobEvent> stateMachine;
    //状态机是否启动
    private boolean stateMachineStart;

    public String getUniqueKey(){
        return String.join("-", taieTenant, taskType, String.valueOf(invokeId));
    }

    public boolean undone(){
        return state.equals(States.JobState.UNSTART.name())
                || state.equals(States.JobState.RUNNING.name())
                || state.equals(States.JobState.RUNNING_TIMEOUT.name());
    }

    public boolean unStart(){
        return execJobId == null
                || state.equals(States.JobState.UNSTART.name());
    }

    public boolean running(){
        return state.equals(States.JobState.RUNNING.name())
                || state.equals(States.JobState.RUNNING_TIMEOUT.name());
    }

    public boolean done(){
        return state.equals(States.JobState.SUCCESS.name())
                || state.equals(States.JobState.FAIL.name())
                || state.equals(States.JobState.TERMINATE.name())
                || state.equals(States.JobState.START_TIMEOUT.name());
    }

    public boolean startOverTime(){
        if(Objects.nonNull(taskExecConfig) && Objects.nonNull(taskExecConfig.getSchedule().getStartTimeOut())){
            return LocalDateTime.now().isAfter(createTime.plusMinutes(taskExecConfig.getSchedule().getStartTimeOut()));
        }
        return false;
    }

    public boolean runningOverTime(){
        if(Objects.nonNull(taskExecConfig) && Objects.nonNull(taskExecConfig.getSchedule().getRunTimeOut())){
            return LocalDateTime.now().isAfter(jobStartTime.plusMinutes(taskExecConfig.getSchedule().getRunTimeOut()));
        }
        return false;
    }

    public int getMaxRetryTime(){
        if(Objects.nonNull(taskExecConfig) && Objects.nonNull(taskExecConfig.getSchedule().getRetryTime())){
            return taskExecConfig.getSchedule().getRetryTime();
        }
        return 0;
    }

    public boolean modifiable(){
        return !scheduling && unStart();
    }

}
