package com.blueland.sys.timetask.web;


import java.util.Date;
import java.util.HashMap;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;

import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.blueland.annotation.Log;
import com.blueland.bo.TucStaffEntity;
import com.blueland.core.util.UserUtils;
import com.blueland.model.TPfSysTimetask;
import com.blueland.result.R;
import com.blueland.service.IParameterService;
import com.blueland.service.ITucStaffService;
import com.blueland.service.SysTimetaskService;
import org.quartz.CronScheduleBuilder;
import org.quartz.CronTrigger;
import org.quartz.Job;
import org.quartz.JobBuilder;
import org.quartz.JobDetail;
import org.quartz.JobKey;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.quartz.TriggerBuilder;
import org.quartz.TriggerKey;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.PathVariable;
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.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;

import com.blueland.config.quartz.service.ScheduleServiceI;
import com.blueland.core.util.StringUtil;
import com.blueland.bo.ParameterEntity;
import com.blueland.bo.SysTimetaskEntity;
import com.blueland.sys.timetask.telnet.TelnetTask;

import common.constant.CommonConstant;
import io.swagger.annotations.Api;
import lombok.extern.slf4j.Slf4j;

import static com.blueland.constant.CommonConstant.*;


@Api(value = "sysTimetask")
@RestController
@Slf4j
@RequestMapping(value = "/api/sysTimetask")
public class SysTimetaskRest {
	@Autowired
	private SysTimetaskService sysTimetaskService;
	@Autowired
	private Scheduler scheduler;
	@Autowired
	private ScheduleServiceI scheduleService;
	@Autowired
	private IParameterService iParameterService;
	
	
	/**
	 *查询list
	 */
	@ResponseBody
	@RequestMapping(value="/list", method = RequestMethod.GET,produces = "application/json;charset=UTF-8")
	public Page<SysTimetaskEntity> listPage(@RequestParam Map<String,Object> queryParams){
    	queryParams.put("orderByColumns", "T1.create_time");
		Page<SysTimetaskEntity> page = sysTimetaskService.findSysTimetaskPageListByParams(queryParams,Integer.parseInt(queryParams.get("pageNum").toString()),Integer.parseInt(queryParams.get("pageSize").toString()));
		return page;
	}
	
	/** 
	 * 搜索对象 
	 **/
	@RequestMapping(value = "",method = RequestMethod.GET,produces = "application/json;charset=UTF-8")
	@ResponseBody
	@CrossOrigin
	public R<Page<SysTimetaskEntity>> list(SysTimetaskEntity sysTimetaskEntity) {
		Page<SysTimetaskEntity> page = this.sysTimetaskService.findPage(sysTimetaskEntity);
		return R.ok(page);
	}

	
	/** 
	 * 查看对象
	 **/
	@RequestMapping(value = "/{id}",method = RequestMethod.GET,produces = "application/json;charset=UTF-8")
	@ResponseBody
	@CrossOrigin
	public R<TPfSysTimetask> view(@PathVariable String id)  {
		TPfSysTimetask sysTimetaskEntity  = sysTimetaskService.getById(id);
		return R.ok(sysTimetaskEntity);
	}

	/** 
	 * 查看对象（支持多条件查询）
	 **/
	@RequestMapping(value = "get",method = RequestMethod.GET,produces = "application/json;charset=UTF-8")
	@ResponseBody
	@CrossOrigin
	public R<TPfSysTimetask> get(SysTimetaskEntity model)  {
		TPfSysTimetask sysTimetaskEntity  = sysTimetaskService.get(model);
		return R.ok(sysTimetaskEntity);
	}
	
	/** 
	 * 新增对象
	 **/
	@Log(busiType = "新增定时调度任务", opType = SAVE, type = "web")
	@RequestMapping(value = "",method = RequestMethod.POST,produces = "application/json;charset=UTF-8")
	@ResponseBody
	@CrossOrigin
	public R<SysTimetaskEntity> save(HttpServletRequest request,@RequestBody SysTimetaskEntity model)  {
		if (sysTimetaskService.count(model) > 0) {
			throw new RuntimeException("此调度任务已存在，任务编码：" + model.getTaskCode());
		}
		TPfSysTimetask timetask = BeanUtil.copyProperties(model, TPfSysTimetask.class);
		//从request获取用户信息
		String userid = UserUtils.getPostCode();
		timetask.setCreateId(userid);
		timetask.setCreateTime(new Date());
		timetask.setAppId(UserUtils.getTenantId());
		sysTimetaskService.save(timetask);
		//本地定时任务
		if(CommonConstant.TASKSTATUS_Y.equals(model.getStatus())){
			if(CommonConstant.TASKTYPE_LOCAL.equals(model.getTaskType())){
				schedulerAdd(model.getAction(), model.getCronExp().trim(), "");
			}else {//远程调用
				if(StringUtil.notEmpty(model.getAction())) {
					ParameterEntity parameter = iParameterService.getBykey("jwt_token");
					if(null != parameter) {
						String authorization = parameter.getPvalue();	
						TelnetTask task = new TelnetTask(authorization, model.getAction(), model.getTaskCode(),model.getDescription());
						schedulerAdd4Telnet(task, model.getCronExp(), "",model.getId());
					}
				}
			}
		}
		return R.ok(model);
	}
	
	/**
	 * 更新对象
	 * @return 
	 **/
	@Log(busiType = "更新定时调度任务", opType = UPDATE, type = "web")
	@RequestMapping(value = "",method = RequestMethod.PUT,produces = "application/json;charset=UTF-8")
	@ResponseBody
	@CrossOrigin
	public R<SysTimetaskEntity> update(HttpServletRequest request,@RequestBody SysTimetaskEntity model)  {
		TPfSysTimetask timetask = BeanUtil.copyProperties(model, TPfSysTimetask.class);
		//从request获取用户信息
		String userid = UserUtils.getPostCode();
		timetask.setUpdateId(userid);
		timetask.setAppId(UserUtils.getTenantId());
		sysTimetaskService.updateById(timetask);
		//本地定时任务
		if(CommonConstant.TASKTYPE_LOCAL.equals(model.getTaskType())){
			schedulerDelete(model.getAction().trim());
			if(CommonConstant.TASKSTATUS_Y.equals(model.getStatus())) {
				schedulerAdd(model.getAction().trim(), model.getCronExp().trim(),"");
			}
		}else {//远程调用
			if(CommonConstant.TASKSTATUS_Y.equals(model.getStatus())) {
				if(StringUtil.notEmpty(model.getAction())) {
					ParameterEntity parameter = iParameterService.getBykey("jwt_token");
					if(null != parameter) {
						String authorization = parameter.getPvalue();	
						TelnetTask task = new TelnetTask(authorization, model.getAction(), model.getTaskCode(),model.getDescription());
						schedulerAdd4Telnet(task, model.getCronExp(), "", model.getId());
					}
				}
			}
		}
		return R.ok(model);
	}
	
	/**
	 * 删除对象
	 * @return 
	 **/
	@Log(busiType = "删除定时调度任务", opType = DELETE, type = "web")
	@RequestMapping(value = "/{id}",method = RequestMethod.DELETE,produces = "application/json;charset=UTF-8")
	@ResponseBody
	@CrossOrigin
	public R<Boolean> delete(HttpServletRequest request,@PathVariable String id) {
		TPfSysTimetask task = sysTimetaskService.getById(id);
		if(CommonConstant.TASKTYPE_LOCAL.equals(task.getTaskType())){
			schedulerDelete(task.getAction().trim());
		}else {
			
		}
		sysTimetaskService.removeById(id);
		return R.ok();
	}
	
	/**
	 *  批量删除对象
	 * @return 
	 **/
	@Log(busiType = "批量删除定时调度任务", opType = DELETE, type = "web")
	@RequestMapping(value = "deleteBatch",method = RequestMethod.DELETE,produces = "application/json;charset=UTF-8")
	@ResponseBody
	@CrossOrigin
	public R<Boolean> deleteBatch(HttpServletRequest request,String[] ids) {
		for (int i = 0; i < ids.length; i++) {
			TPfSysTimetask task = sysTimetaskService.getById(ids[i]);
			if(CommonConstant.TASKTYPE_LOCAL.equals(task.getTaskType())){
				schedulerDelete(task.getAction().trim());
			}else {
			}
			sysTimetaskService.removeById(ids[i]);
		}
		return R.ok();
	}
	
	/**
	 * 暂停定时任务
	 * @param
	 * @return
	 */
	@Log(busiType = "暂停定时调度任务", opType = JOB, type = "web")
	@RequestMapping(value = "/pause", method = RequestMethod.POST)
	@ResponseBody
	@CrossOrigin
	public R<Boolean> pauseJob(HttpServletRequest request,@RequestBody SysTimetaskEntity model) {
		String status = CommonConstant.STATUS_SUCCESS;
		try {
			if(CommonConstant.TASKTYPE_LOCAL.equals(model.getTaskType())){
				//scheduler.pauseJob(JobKey.jobKey(model.getAction().trim()));
				scheduleService.stopTask(model);
			}else {
				this.schedulerDelete4Telnet(model.getId());	
			}
		} catch (Exception e) {
			e.printStackTrace();
			status = CommonConstant.STATUS_FAILED;
			throw new RuntimeException("暂停定时任务失败");
		}
		model.setStatus(CommonConstant.TASKSTATUS_N);
		model.setUpdateId("admin");
		TPfSysTimetask timetask = BeanUtil.copyProperties(model, TPfSysTimetask.class);
		sysTimetaskService.updateById(timetask);
		return R.ok();
	}

	/**
	 * 启动定时任务
	 * @param
	 * @return
	 */
	@Log(busiType = "恢复定时调度任务", opType = JOB, type = "web")
	@RequestMapping(value = "/resume", method = RequestMethod.POST)
	@ResponseBody
	@CrossOrigin
	public R<Boolean> resumeJob(HttpServletRequest request,@RequestBody SysTimetaskEntity model) {
		String status = CommonConstant.STATUS_SUCCESS;
		model.setStatus(CommonConstant.TASKSTATUS_Y);
		model.setUpdateId("admin");
		TPfSysTimetask timetask = BeanUtil.copyProperties(model, TPfSysTimetask.class);
		sysTimetaskService.updateById(timetask);
		try {
			if(CommonConstant.TASKTYPE_LOCAL.equals(model.getTaskType())){
				//scheduler.resumeJob(JobKey.jobKey(model.getAction().trim()));
				scheduleService.startTask(model);
			}else {
				//调用远程启动接口
				if(StringUtil.notEmpty(model.getAction())) {
					ParameterEntity parameter = iParameterService.getBykey("jwt_token");
					if(null != parameter) {
						String authorization = parameter.getPvalue();	
						TelnetTask task = new TelnetTask(authorization,model.getAction(), model.getTaskCode(),model.getDescription());
						schedulerAdd4Telnet(task, model.getCronExp(), "",model.getId());
					}
				}
			}
		} catch (Exception e) {
			throw new RuntimeException("恢复定时任务失败");
		}
		return R.ok();
	}
	
	
	
	/**
	 * 添加定时任务
	 * @param jobClassName
	 * @param cronExpression
	 * @param parameter
	 */
	private void schedulerAdd(String jobClassName, String cronExpression, String parameter) {
		try {
			// 启动调度器
			scheduler.start();

			// 构建job信息
			JobDetail jobDetail = JobBuilder.newJob(getClass(jobClassName).getClass()).withIdentity(jobClassName).build();
			if(org.apache.commons.lang3.StringUtils.isNotEmpty(parameter) ){
				jobDetail = JobBuilder.newJob(getClass(jobClassName).getClass()).withIdentity(jobClassName).usingJobData("parameter", parameter).build();
			}
			
			// 表达式调度构建器(即任务执行的时间)
			CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(cronExpression);

			// 按新的cronExpression表达式构建一个新的trigger
			CronTrigger trigger = TriggerBuilder.newTrigger().withIdentity(jobClassName).withSchedule(scheduleBuilder).build();

			scheduler.scheduleJob(jobDetail, trigger);
		} catch (SchedulerException e) {
			log.error(e.toString());
			throw new RuntimeException("创建定时任务失败");
		} catch (Exception e) {
			log.error(e.toString());
			throw new RuntimeException("后台找不到该类名任务");
		}
	}
	
	/**
	 * 添加定时任务(远程)
	 * @param telnetTask
	 * @param cronExpression
	 * @param parameter
	 */
	private void schedulerAdd4Telnet(TelnetTask telnetTask, String cronExpression, String parameter, String identity) {
		try {
			//先删除
			this.schedulerDelete4Telnet(identity);
			// 启动调度器
			scheduler.start();
			// 构建job信息
			JobDetail jobDetail = JobBuilder.newJob(telnetTask.getClass()).withIdentity(identity).build();
			if(org.apache.commons.lang3.StringUtils.isNotEmpty(parameter) ){
				jobDetail = JobBuilder.newJob(telnetTask.getClass()).withIdentity(identity).usingJobData("parameter", parameter).build();
			}
			Map<String,String> param = new HashMap<String,String>();
			param.put("bizId",telnetTask.getBizId());
			param.put("bizType",telnetTask.getBizType());
	        param.put("authorization",telnetTask.getAuthorization());
	        param.put("url",telnetTask.getUrl());
			jobDetail.getJobDataMap().put("data",param);
			
			// 表达式调度构建器(即任务执行的时间)
			CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(cronExpression);

			// 按新的cronExpression表达式构建一个新的trigger
			CronTrigger trigger = TriggerBuilder.newTrigger().withIdentity(identity).withSchedule(scheduleBuilder).build();

			scheduler.scheduleJob(jobDetail, trigger);
		} catch (SchedulerException e) {
			log.error(e.toString());
			throw new RuntimeException("创建定时任务失败");
		} catch (Exception e) {
			log.error(e.toString());
			throw new RuntimeException("后台找不到该类名任务");
		}
	}
	
	/**
	 * 删除定时任务
	 * @param jobClassName
	 */
	private void schedulerDelete(String jobClassName) {

		try {
			scheduler.pauseTrigger(TriggerKey.triggerKey(jobClassName));
			scheduler.unscheduleJob(TriggerKey.triggerKey(jobClassName));
			scheduler.deleteJob(JobKey.jobKey(jobClassName));
		} catch (Exception e) {
			throw new RuntimeException("删除定时任务失败");
		}
	}
		
	/**
	 * 删除定时任务(远程)
	 * @param
	 */
	private void schedulerDelete4Telnet(String identity) {
		try {
			scheduler.pauseTrigger(TriggerKey.triggerKey(identity));
			scheduler.unscheduleJob(TriggerKey.triggerKey(identity));
			scheduler.deleteJob(JobKey.jobKey(identity));
		} catch (Exception e) {
			throw new RuntimeException("删除定时任务失败");
		}
	}
	
	private static Job getClass(String classname) throws Exception {
		Class<?> clz = Class.forName(classname);
		return (Job) clz.newInstance();
	}
	
}



