package com.alibaba.pokemon.bulbasaur.schedule;

import java.util.Date;

import com.alibaba.pokemon.bulbasaur.core.CoreModule;
import com.alibaba.pokemon.bulbasaur.core.Result;
import com.alibaba.pokemon.bulbasaur.core.model.State;
import com.alibaba.pokemon.bulbasaur.core.model.StateLike;
import com.alibaba.pokemon.bulbasaur.exception.BizException;
import com.alibaba.pokemon.bulbasaur.persist.PersistHelper;
import com.alibaba.pokemon.bulbasaur.persist.PersistMachine;
import com.alibaba.pokemon.bulbasaur.persist.domain.JobDO;
import com.alibaba.pokemon.bulbasaur.persist.domain.ProcessDO;
import com.alibaba.pokemon.bulbasaur.persist.domain.StateDOExample;
import com.alibaba.pokemon.bulbasaur.persist.domain.StateDOWithBLOBs;
import com.alibaba.pokemon.bulbasaur.persist.mapper.*;
import com.alibaba.pokemon.bulbasaur.persist.mapper.*;
import com.alibaba.pokemon.bulbasaur.schedule.process.JobHelper;
import com.alibaba.pokemon.bulbasaur.schedule.util.CommentUtil;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * 增加了调度能力
 * User: yunche.ch - - - - (ว ˙o˙)ง
 * Date: 13-11-1
 * Time: 下午6:03
 */
public class ScheduleMachine extends PersistMachine {
    private final static Logger logger = LoggerFactory.getLogger(ScheduleMachine.class);
    public static final int EXE_INFO_MAX_LENGTH = 4900;
    //需要构造的时候传入
    private JobHelper jobHelper;
    private JobDOMapper jobDOMapper;
    private StateDOMapper stateDOMapper;

    protected ScheduleMachine(String bizId, String processName, int processVersion, ProcessDO processDO,
                              ProcessDOMapper processDOMapper, StateDOMapper stateDOMapper,
                              PersistHelper _persistHelper, JobDOMapper jobDOMapper, JobHelper _jobHelper,
                              TaskDOMapper taskDOMapper, ParticipationDOMapper participationDOMapper) {
        super(bizId, processName, processVersion, processDO, processDOMapper, stateDOMapper, _persistHelper,
            taskDOMapper, participationDOMapper, jobDOMapper);
        this.jobDOMapper = jobDOMapper;
        this.stateDOMapper = stateDOMapper;
        this.jobHelper = _jobHelper;
    }

    @Override
    protected Result run_atom(final StateLike currentState) {
        Result result = new Result();
        try {
            result = super.run_atom(currentState);
        } catch (RuntimeException e) {
            result.setContinue(false);
            if (e instanceof BizException) {
                // 在这里需要打监控信息 需要判断是否是重试次数完了什么的
                logger.error("单节点执行中发生业务错误:" + currentState.getStateName(), e.getMessage());

                // 在节点上面存一下执行信息
                StateDOWithBLOBs stateDOWithBLOBs = new StateDOWithBLOBs();
                stateDOWithBLOBs.setGmtModified(new Date());
                stateDOWithBLOBs.setExeInfo(subString(e.getMessage()));
                StateDOExample stateDOExample = new StateDOExample();
                stateDOExample.createCriteria().andOwnSignEqualTo(CoreModule.getInstance().getOwnSign())
                    .andStateNameEqualTo(currentState.getStateName())
                    .andBizIdEqualTo(currentState.getBizId());
                stateDOMapper.updateByExampleSelective(stateDOWithBLOBs, stateDOExample);

                //判断是否配置了重试，没配置直接扔出去
                if (currentState instanceof State) {
                    if (StringUtils.isBlank(((State)currentState).getRepeatList())) {
                        throw e;
                    }
                }
                // 存在重试记录的，更新重试记录
                ProcessDO currentProcessDO = getProcessDO();
                JobDO jobDO = jobHelper.getJob(getProcessDO().getBizId());
                if (jobDO != null) {
                    // 如果存在 就更新错误栈 重试次数以及时间
                    jobHelper.updateJobStack(jobDO, e.getCause());
                    logger.info(String
                        .format("流程[%s]的节点[%s],还可以重试[%s]次！", getProcessDO().getBizId(), jobDO.getStateName(),
                            jobDO.getRepeatTimes()));
                    return result;
                }

                // 插入一个新的job 等待重试
                jobHelper.add(currentProcessDO.getBizId(), currentProcessDO.getDefinitionName(), currentState, e);

                return result;
            } else {
                throw e;
            }

        }

        return result;

    }

    private String subString(String message) {

        if (CommentUtil.getLength(message) <= EXE_INFO_MAX_LENGTH) {
            return StringUtils.remove(message, "'");
        } else {
            return StringUtils.remove(CommentUtil.subStr(message, EXE_INFO_MAX_LENGTH), "'");
        }

    }

}

