package cn.axzo.workflow.core.conf;

import cn.axzo.workflow.core.engine.behavior.CustomActivityBehaviorFactory;
import cn.axzo.workflow.core.engine.id.DistributedTimeBasedIdGenerator;
import cn.axzo.workflow.core.engine.job.AsyncAbortProcessInstanceHandler;
import cn.axzo.workflow.core.engine.job.AsyncApproveTaskJobHandler;
import cn.axzo.workflow.core.engine.job.AsyncBpmnProcessActivityJobHandler;
import cn.axzo.workflow.core.engine.job.AsyncCancelProcessInstanceHandler;
import cn.axzo.workflow.core.engine.job.AsyncCountersignUserTaskJobHandler;
import cn.axzo.workflow.core.engine.job.AsyncExtTaskInstJobHandler;
import cn.axzo.workflow.core.engine.job.AsyncRejectTaskJobHandler;
import cn.axzo.workflow.core.engine.job.AsyncTransferUserTaskJobHandler;
import cn.axzo.workflow.core.engine.job.exception.handler.CustomAsyncRunnableExecutionExceptionHandler;
import cn.axzo.workflow.core.engine.persistence.CustomMybatisHistoricProcessInstanceDataManager;
import cn.axzo.workflow.core.service.BpmnProcessActivityService;
import cn.axzo.workflow.core.service.ExtAxHiTaskInstService;
import com.google.common.collect.Lists;
import org.flowable.common.engine.api.delegate.event.FlowableEventListener;
import org.flowable.common.engine.impl.history.HistoryLevel;
import org.flowable.form.spring.SpringFormEngineConfiguration;
import org.flowable.spring.SpringProcessEngineConfiguration;
import org.flowable.spring.boot.EngineConfigurationConfigurer;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.core.StringRedisTemplate;

import static org.flowable.common.engine.impl.AbstractEngineConfiguration.DB_SCHEMA_UPDATE_TRUE;

/**
 * Flowable 引擎相关全局配置
 *
 * @author wangli
 * @since 2023/7/13 11:18
 */
@Configuration
public class FlowableConfiguration {

    @Bean
    public EngineConfigurationConfigurer<SpringProcessEngineConfiguration> processEngineConfigurer(
            ObjectProvider<FlowableEventListener> listeners,
            CustomActivityBehaviorFactory customActivityBehaviorFactory,
            StringRedisTemplate stringRedisTemplate,
            ExtAxHiTaskInstService extAxHiTaskInstService,
            BpmnProcessActivityService bpmnProcessActivityService) {
        return configuration -> {
            configuration.setEnableHistoricTaskLogging(true);
            configuration.setHistoryLevel(HistoryLevel.AUDIT);
            configuration.setHistory(HistoryLevel.AUDIT.getKey());
            configuration.setEventListeners(Lists.newArrayList(listeners));
            configuration.setActivityBehaviorFactory(customActivityBehaviorFactory);
            configuration.setDatabaseSchemaUpdate(DB_SCHEMA_UPDATE_TRUE);
            configuration.setEnableSafeBpmnXml(false);
            //            configuration.setCreateDiagramOnDeploy(false);
//            configuration.setIdGenerator(new TimeBasedIdGenerator());
            configuration.setIdGenerator(new DistributedTimeBasedIdGenerator(stringRedisTemplate));
            configuration.setHistoricProcessInstanceDataManager(new CustomMybatisHistoricProcessInstanceDataManager(configuration));
            // 自定义的异步任务处理器
            configuration.addCustomJobHandler(new AsyncApproveTaskJobHandler());
            configuration.addCustomJobHandler(new AsyncRejectTaskJobHandler(extAxHiTaskInstService));
            configuration.addCustomJobHandler(new AsyncExtTaskInstJobHandler(extAxHiTaskInstService));
            configuration.addCustomJobHandler(new AsyncTransferUserTaskJobHandler());
            configuration.addCustomJobHandler(new AsyncCountersignUserTaskJobHandler(extAxHiTaskInstService));
            configuration.addCustomJobHandler(new AsyncCancelProcessInstanceHandler(extAxHiTaskInstService));
            configuration.addCustomJobHandler(new AsyncAbortProcessInstanceHandler(extAxHiTaskInstService));
            configuration.addCustomJobHandler(new AsyncBpmnProcessActivityJobHandler(bpmnProcessActivityService));
            // 异步任务异常重试时间间隔
            configuration.setDefaultFailedJobWaitTime(30);
            configuration.setAsyncFailedJobWaitTime(30);
            configuration.setCustomAsyncRunnableExecutionExceptionHandlers(Lists.newArrayList(new CustomAsyncRunnableExecutionExceptionHandler()));
        };
    }

    @Bean
    public EngineConfigurationConfigurer<SpringFormEngineConfiguration> formEngineConfigurer() {
        return configuration -> configuration.setDatabaseSchemaUpdate(DB_SCHEMA_UPDATE_TRUE);
    }

    @Bean
    public CustomActivityBehaviorFactory customActivityBehaviorFactory(ExtAxHiTaskInstService hiTaskInstService) {
        CustomActivityBehaviorFactory customActivityBehaviorFactory = new CustomActivityBehaviorFactory();
        customActivityBehaviorFactory.setHiTaskInstService(hiTaskInstService);
        return customActivityBehaviorFactory;
    }

}
