package com.xxl.job.admin.controller.custom;

import javax.annotation.Resource;

import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.persagy.common.utils.StringUtil;
import com.xxl.job.admin.core.model.DictQuery;
import com.xxl.job.admin.core.model.XxlJobGroup;
import com.xxl.job.admin.core.model.XxlJobInfo;
import com.xxl.job.admin.core.model.XxlJobInfoIdValid;
import com.xxl.job.admin.core.model.XxlJobInfoValid;
import com.xxl.job.admin.core.route.ExecutorRouteStrategyEnum;
import com.xxl.job.admin.core.scheduler.MisfireStrategyEnum;
import com.xxl.job.admin.core.scheduler.ScheduleTypeEnum;
import com.xxl.job.admin.core.thread.JobTriggerPoolHelper;
import com.xxl.job.admin.core.trigger.TriggerTypeEnum;
import com.xxl.job.admin.dao.XxlJobGroupDao;
import com.xxl.job.admin.dao.XxlJobInfoDao;
import com.xxl.job.admin.service.XxlJobService;
import com.xxl.job.core.biz.model.ReturnT;
import com.xxl.job.core.constant.CommonConstant;
import com.xxl.job.core.enums.ExecutorBlockStrategyEnum;


/**
 * 暴露接口
 * @version 1.0.0
 * @company persagy 
 * @author zhangqiankun
 * @date 2021年9月24日 下午2:37:55
 */
@RestController
//@Api(tags = "任务触发点设置")
@RequestMapping(value = "/customInfo", method = {RequestMethod.POST})
public class CustomInfoController {

	@Resource
	private XxlJobService xxlJobService;
	
	@Resource
	private XxlJobInfoDao xxlJobInfoDao;
	
	@Resource
	private XxlJobGroupDao xxlJobGroupDao;
	
	@Autowired
	private CustomInfoHandler customInfoHandler;
	
	/**
	 * 旧数据转移
	 * 
	 * @return
	 */
	@RequestMapping(value = "/transfer")
	public ReturnT<String> transfer() {
		return customInfoHandler.transfer();
	}
	
	@RequestMapping(value = "/addOrUpdate2Start")
	public ReturnT<String> addOrUpdateAndStart(@RequestBody @Validated XxlJobInfoValid valid) {
		XxlJobInfo jobInfo = new XxlJobInfo();
		BeanUtils.copyProperties(valid, jobInfo);

		if (StringUtil.isNotBlank(valid.getCallBackUrl())) {
			valid.getExecutorParam().put("callBackUrl", valid.getCallBackUrl());
		}
		if (StringUtil.isNotBlank(valid.getJobCron())) {
			jobInfo.setScheduleConf(valid.getJobCron());
		}
		jobInfo.setExecutorParam(valid.getExecutorParam().toJSONString());
		
		if (valid.getId() == null) {
			xxlJobService.add(jobInfo);
		} else {
			xxlJobService.update(jobInfo);
		}
		// 启动任务
		return xxlJobService.start(jobInfo.getId());
	}
	
	@RequestMapping(value = "/add")
	public ReturnT<String> add(@RequestBody @Validated XxlJobInfoValid valid) {
		XxlJobInfo jobInfo = new XxlJobInfo();
		BeanUtils.copyProperties(valid, jobInfo);
		if (StringUtil.isNotBlank(valid.getCallBackUrl())) {
			valid.getExecutorParam().put("callBackUrl", valid.getCallBackUrl());
		}
		if (StringUtil.isNotBlank(valid.getJobCron())) {
			jobInfo.setScheduleConf(valid.getJobCron());
		}
		jobInfo.setExecutorParam(valid.getExecutorParam().toJSONString());
		return xxlJobService.add(jobInfo);
	}
	
	@RequestMapping(value = "/update")
	public ReturnT<String> update(@RequestBody @Validated XxlJobInfoValid valid) {
		XxlJobInfo jobInfo = new XxlJobInfo();
		BeanUtils.copyProperties(valid, jobInfo);
		if (StringUtil.isNotBlank(valid.getCallBackUrl())) {
			valid.getExecutorParam().put("callBackUrl", valid.getCallBackUrl());
		}
		if (StringUtil.isNotBlank(valid.getJobCron())) {
			jobInfo.setScheduleConf(valid.getJobCron());
		}
		jobInfo.setExecutorParam(valid.getExecutorParam().toJSONString());
		return xxlJobService.update(jobInfo);
	}
	
	@RequestMapping(value = "/remove")
	public ReturnT<String> remove(@RequestBody @Validated XxlJobInfoIdValid valid) {
		return xxlJobService.remove(valid.getId());
	}
	
	@RequestMapping(value = "/stop")
	public ReturnT<String> pause(@RequestBody @Validated XxlJobInfoIdValid valid) {
		return xxlJobService.stop(valid.getId());
	}
	
	@RequestMapping(value = "/start")
	public ReturnT<String> start(@RequestBody @Validated XxlJobInfoIdValid valid) {
		return xxlJobService.start(valid.getId());
	}
	
	@RequestMapping(value = "/trigger")
	public ReturnT<String> triggerJob(@RequestBody @Validated XxlJobInfoIdValid valid) {
		XxlJobInfo xxlJobInfo = xxlJobInfoDao.loadById(valid.getId());
		if (xxlJobInfo == null || StringUtil.isBlank(xxlJobInfo.getExecutorParam())) {
			throw new IllegalArgumentException("非法请求，任务参数不存在");
		}
		
		XxlJobGroup xxlJobGroup = xxlJobGroupDao.load(xxlJobInfo.getJobGroup());
		if (xxlJobGroup == null) {
			throw new IllegalArgumentException("非法请求，执行器不存在");
		}
		
		JobTriggerPoolHelper.trigger(xxlJobInfo.getId(), TriggerTypeEnum.MANUAL, -1, null, xxlJobInfo.getExecutorParam(), xxlJobGroup.getAddressList());
		return ReturnT.SUCCESS;
	}
	
	
	/************************************************ 字典值查询  *********************************************/
	
	@RequestMapping("/dictQuery")
	//@ApiOperation(value = "字典值查询")
	public String remove(@RequestBody @Validated DictQuery query) {
		JSONObject content = new JSONObject();
		if (CommonConstant.EXECUTOR_ROUTE_STRATEGY.equals(query.getQueryType())) {
			for (ExecutorRouteStrategyEnum item : ExecutorRouteStrategyEnum.values()) {
				content.put(item.name(), item.getTitle());
	        }
		} else if (CommonConstant.EXECUTOR_BLOCK_STRATEGY.equals(query.getQueryType())) {
			for (ExecutorBlockStrategyEnum item : ExecutorBlockStrategyEnum.values()) {
				content.put(item.name(), item.getTitle());
            }
		} else if (CommonConstant.MISFIRE_STRATEGY.equals(query.getQueryType())) {
			for (MisfireStrategyEnum item : MisfireStrategyEnum.values()) {
				content.put(item.name(), item.getTitle());
            }
		} else if (CommonConstant.SCHEDULE_TYPE.equals(query.getQueryType())) {
			for (ScheduleTypeEnum item : ScheduleTypeEnum.values()) {
				content.put(item.name(), item.getTitle());
            }
		} else {
			content = null;
		}
		ReturnT<JSONObject> returnT = new ReturnT<JSONObject>(content);
		return JSON.toJSONString(returnT);
	}
	
}
