package com.steerinfo.task;

import com.steerinfo.ems.Utils.DateUtils;
import com.steerinfo.ems.emsetiming.service.IEmsETimingService;
import com.steerinfo.ems.emswaterrealtime.service.IEmsWaterRealtimeService;
import com.steerinfo.ems.ifemsmesactitem.service.IIfEmsMesActitemService;
import com.steerinfo.ems.ifmesemsproductorder.service.IIfMesEmsProductorderService;
import com.steerinfo.ems.ifmesemsswapfile.service.IIfMesEmsSwapfileService;
import com.steerinfo.ems.ifmesemswatermonitor.service.IIfMesEmsWatermonitorService;
import com.steerinfo.ems.mesemsdieseloil.service.IMesEmsDieseloilService;
import com.steerinfo.ems.tcm0312.controller.TCm0312Controller;
import com.steerinfo.ems.trmactvalue.service.ITRmActValueService;
import com.steerinfo.ems.trmbalancevalue.service.ITRmBalanceValueService;
import com.steerinfo.ems.trmcalpoint.service.ITRmCalpointService;
import com.steerinfo.ems.trmcalpointvalue.service.ITRmCalpointValueService;
import com.steerinfo.ems.trmdfvalue.service.ITRmDfValueService;
import com.steerinfo.ems.trmdwvalue.service.ITRmDwValueService;
import com.steerinfo.ems.trmindexvalue.service.ITRmIndexValueService;
import com.steerinfo.ems.trmplanvalue.service.ITRmPlanValueService;
import com.steerinfo.ems.trmtransfereactvalue.service.ITRmTransfereActValueService;
import com.steerinfo.ems.trmworkprocmaterialvalue.service.ITRmWorkprocMaterialValueService;
import com.steerinfo.ems.trmworkprocproductvalue.service.ITRmWorkprocProductValueService;
import com.steerinfo.ems.usagedata.service.IUsageDataService;
import com.steerinfo.ems.zghbjkbzlog.service.IZghbjkbzLogService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.scheduling.SchedulingException;
import org.springframework.scheduling.TaskScheduler;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.SchedulingConfigurer;
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
import org.springframework.scheduling.config.ScheduledTaskRegistrar;
import org.springframework.scheduling.support.CronTrigger;
import org.springframework.stereotype.Service;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ScheduledFuture;

@EnableScheduling
@Service(value = "springCronTask")
public class SpringCronTask implements SchedulingConfigurer{
	
	private static final Logger logger = LoggerFactory.getLogger(SpringCronTask.class);
	
	private ScheduledTaskRegistrar taskRegistrar;
	
	private Map<String, ScheduledFuture<?>> taskFutures = new ConcurrentHashMap<String, ScheduledFuture<?>>();
	
	@Autowired
    private JdbcTemplate jdbcTemplate;
	@Autowired
    IIfMesEmsSwapfileService ifMesEmsSwapfileService;
    @Autowired
    IIfMesEmsProductorderService ifMesEmsProductorderService;
    @Autowired
    ITRmWorkprocMaterialValueService tRmWorkprocMaterialValueService;
    @Autowired
    ITRmWorkprocProductValueService tRmWorkprocProductValueService;
    @Autowired
	ITRmCalpointValueService tRmCalpointValueService;
	@Autowired
    IUsageDataService usageDataService;
	@Autowired
    ITRmActValueService tRmActValueService;
	@Autowired
    ITRmPlanValueService tRmPlanValueService;
	@Autowired
	IEmsETimingService emsETimingService;
	@Autowired
	TCm0312Controller tCm0312Controller;
	@Autowired
	IIfMesEmsWatermonitorService ifMesEmsWatermonitorService;
	@Autowired
	IIfEmsMesActitemService ifEmsMesActitemService;
	@Autowired
	ITRmIndexValueService tRmIndexValueService;
	@Autowired
    ITRmBalanceValueService tRmBalanceValueService;
	@Autowired
	IZghbjkbzLogService zghbjkbzLogService;
	@Autowired
    IMesEmsDieseloilService mesEmsDieseloilService;
	@Autowired
	ITRmTransfereActValueService tRmTransfereActValueService;
	@Autowired
    ITRmDwValueService tRmDwValueService;
	@Autowired
    ITRmCalpointService tRmCalpointService;
	@Autowired
    ITRmDfValueService tRmDfValueService;
	@Autowired
	IEmsWaterRealtimeService emsWaterRealtimeService;

	/**
	 * SchedulingConfigurer接口的方法实现，加载后自动运行
	 */
	@Override
	public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
		ThreadPoolTaskScheduler taskScheduler = new ThreadPoolTaskScheduler();
		taskScheduler.setThreadNamePrefix("ems-task-");
		taskScheduler.setPoolSize(4);
		taskScheduler.initialize();
		taskRegistrar.setTaskScheduler(taskScheduler);
		
		this.taskRegistrar = taskRegistrar;
		// 初始化任务
		String sql = "select * from TASK_CONF order by id";
		List<Map<String, Object>> l = jdbcTemplate.queryForList(sql);
		if (l!=null && l.size()>0){
			for(int i =0; i<l.size(); i++){
				Map<String, Object> m = (Map<String, Object>)l.get(i);
				String taskId = m.get("ID").toString();
				String cron = m.get("CRON").toString();
				String status = m.get("STATUS") == null ? "" : m.get("STATUS").toString();
				if(status.equalsIgnoreCase("1") && !taskFutures.containsKey(taskId)){
					addTask(taskId, cron);
				}
				if(status.equalsIgnoreCase("0") && taskFutures.containsKey(taskId)){
					cancelTriggerTask(taskId);
				}
				logger.info("定时任务-" + taskId + " cron表达式：" + cron);
			}
		}
	}
	
	/**
	 * 添加定时任务(初始化)
	 * 
	 * @param taskId
	 * @param cron
	 */
	public void addTask(String taskId, String cron) {
		if (!taskFutures.containsKey(taskId)) {
			TaskScheduler scheduler = taskRegistrar.getScheduler();
			ScheduledFuture<?> future = scheduler.schedule(doTask(taskId), new CronTrigger(cron));
			taskFutures.put(taskId, future);
			logger.info("当前定时任务队列长度：" + taskFutures.size());
		} else {
			throw new SchedulingException("the taskId[" + taskId + "] was added.");
		}
	}
	
	/**
	 * 添加或者更新定时任务
	 * 
	 * @param taskId
	 */
	public void updateTask(String taskId) {
		if(taskFutures.containsKey(taskId)){
			cancelTriggerTask(taskId);
		}
		TaskScheduler scheduler = taskRegistrar.getScheduler();
		ScheduledFuture<?> future = scheduler.schedule(doTask(taskId), new CronTrigger(getCron(taskId)));
		taskFutures.put(taskId, future);
		logger.info("当前定时任务队列长度：" + taskFutures.size());
	}
	
	/**
	 * 取消任务
	 * @param taskId
	 */
	public void cancelTriggerTask(String taskId){
		ScheduledFuture<?> future = taskFutures.get(taskId);
	      if (future != null){
	         future.cancel(true);
	      }
	      taskFutures.remove(taskId);
	}
	
	/**
	 * 业务处理
	 * 
	 * @param taskId
	 * @return
	 */
	private Runnable doTask(String taskId) {
		Properties props = System.getProperties(); // 系统属性
		return new Runnable() {
            @Override
            public void run() {
            	if(!props.getProperty("os.name").equalsIgnoreCase("linux")){
            		System.out.println("操作系统：" + props.getProperty("os.name") + ", 非linux环境不运行定时任务");
            		return;
            	}
				if (taskId.equalsIgnoreCase("101")) { // 定时任务1的业务处理-MES数据同步
					logger.info("定时任务触发时间：" + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
					long start = new Date().getTime();
					ifMesEmsSwapfileService.synchronousMesAnEmsData(); // 获取MES投入产出数据
					ifMesEmsProductorderService.synchronousMesAnEmsData(); // 获取MES生产计划数据
					usageDataService.getAutoSum(DateUtils.dateStr(new Date(start - 24*3600*1000L), "yyyy-MM-dd")); // 统计自动上传的能源上报数据（昨日）
					mesEmsDieseloilService.synchronousMesEmsData(); // 获取MES柴油数据
					logger.info("定时任务"+taskId+"执行时长：" + (new Date().getTime() - start)/1000 + "秒");
				} else if (taskId.equalsIgnoreCase("102")) {
					// 计量点定时任务
					long start = new Date().getTime();
					tRmCalpointValueService.statData(new Date());
					logger.info("定时任务"+taskId+"执行时长：" + (new Date().getTime() - start)/1000 + "秒");
				} else if (taskId.equalsIgnoreCase("103")) {
					long start = new Date().getTime();
					tRmActValueService.statDataforDay();// 每日数据统计（实绩定时任务）
					logger.info("定时任务"+taskId+"执行时长：" + (new Date().getTime() - start)/1000 + "秒");
				} else if (taskId.equalsIgnoreCase("104")) {
					long start = new Date().getTime();
					tRmPlanValueService.state();// 每日数据统计（计划定时任务）
					logger.info("定时任务"+taskId+"执行时长：" + (new Date().getTime() - start)/1000 + "秒");
				} else if (taskId.equalsIgnoreCase("105")) {
					// 先计算产品，因为原材料计算单耗需要产品实绩数据参与计算
					long start = new Date().getTime();
					tRmWorkprocProductValueService.setDate(new Date()); // 产品实绩产量、产品计划数据维护
					tRmWorkprocMaterialValueService.setDate(new Date()); // 原材料数据维护
					logger.info("定时任务"+taskId+"执行时长：" + (new Date().getTime() - start)/1000 + "秒");
				} else if (taskId.equalsIgnoreCase("106")) {
					// 获取MES水质监测数据
					long start = new Date().getTime();
					ifMesEmsWatermonitorService.synchronousMesAnEmsData();
					// 生成人工录入监测数据
					tCm0312Controller.getmanualdata();
					logger.info("定时任务"+taskId+"执行时长：" + (new Date().getTime() - start)/1000 + "秒");
				} else if (taskId.equalsIgnoreCase("107")) { // 电统计(从南瑞到EMS)
					long start = new Date().getTime();
					emsETimingService.getData();
					logger.info("定时任务"+taskId+"执行时长：" + (new Date().getTime() - start)/1000 + "秒");
				} else if (taskId.equalsIgnoreCase("108")) {
					// 从IF_MES_EMS_WATERMONITOR表获取水质监测数据到T_CM_0318表
					tCm0312Controller.synchronousData();
				} else if (taskId.equalsIgnoreCase("109")) { // 电计量点班数据计算
					tRmCalpointValueService.statDataShift(new Date());
				} else if (taskId.equalsIgnoreCase("110")) {
					// 能耗数据获取
					ifEmsMesActitemService.getUploadData();
				} else if (taskId.equalsIgnoreCase("111")) {
					// 指标管理数据生成
					long start = new Date().getTime();
					tRmIndexValueService.statData();
					logger.info("定时任务"+taskId+"执行时长：" + (new Date().getTime() - start)/1000 + "秒");
				} else if (taskId.equalsIgnoreCase("112")) {
					// 能源上报_晋泰信和
					usageDataService.autoUpload();
				} else if(taskId.equalsIgnoreCase("113")){
				    //平衡数据维护
					long start = new Date().getTime();
                    tRmBalanceValueService.state();
                    // 上报项目数据维护
                    tRmDwValueService.state(new Date());
                    logger.info("定时任务"+taskId+"执行时长：" + (new Date().getTime() - start)/1000 + "秒");
                } else if(taskId.equalsIgnoreCase("114")){
				    // 环保监控记录定时任务
                	zghbjkbzLogService.record();
                } else if(taskId.equalsIgnoreCase("115")){
				    // 月初自动生成宾馆转供电记录
                	long start = new Date().getTime();
                	tRmTransfereActValueService.createRecord();
                	logger.info("定时任务"+taskId+"执行时长：" + (new Date().getTime() - start)/1000 + "秒");
                } else if(taskId.equalsIgnoreCase("116")){
				    // 动力、水小时表定时统计（自动补全24小时内的小时用量值）
                	long start = new Date().getTime();
                	tRmCalpointService.statHourData();
                	logger.info("定时任务"+taskId+"执行时长：" + (new Date().getTime() - start)/1000 + "秒");
                } else if(taskId.equalsIgnoreCase("117")){
				    // 财务投入产出数据生成
                	long start = new Date().getTime();
                	tRmDfValueService.state(new Date());
                	logger.info("定时任务"+taskId+"执行时长：" + (new Date().getTime() - start)/1000 + "秒");
                } else if(taskId.equalsIgnoreCase("118")){
				    // 财务投入产出数据MES产量补全
                	long start = new Date().getTime();
                	tRmDfValueService.state(new Date());
                	logger.info("定时任务"+taskId+"执行时长：" + (new Date().getTime() - start)/1000 + "秒");
                } else if(taskId.equalsIgnoreCase("120")){
					// 获取大用户水系统数据 5分钟一次
					long start = new Date().getTime();
					emsWaterRealtimeService.getWaterListByArmMeter();
					emsWaterRealtimeService.dataGeneration();
					logger.info("定时任务"+taskId+"执行时长：" + (new Date().getTime() - start)/1000 + "秒");
				} else if(taskId.equalsIgnoreCase("121")){
					// 根据计量点配置生成水数据 10分钟一次
					long start = new Date().getTime();
					emsWaterRealtimeService.getWaterTenMinutes();
					logger.info("定时任务"+taskId+"执行时长：" + (new Date().getTime() - start)/1000 + "秒");
				}
            }
        };
	}
	
	/**
	 * 获取任务时间表达式
	 * @param taskId
	 * @return
	 */
	public String getCron(String taskId) {
		String sql = "select cron from TASK_CONF t where id = ?";
		return jdbcTemplate.queryForObject(sql, new Object[]{taskId}, String.class);
    }
}
