package com.steerinfo.ems.trmcalpoint.service.impl;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.steerinfo.ems.Utils.EmsEAiUtil;
import com.steerinfo.ems.emseaihoursumtab1.mapper.EmsEAiHourSumTab1Mapper;
import com.steerinfo.ems.emseaihoursumtab1.model.EmsEAiHourSumTab1;
import com.steerinfo.ems.emseaihoursumtab1org.mapper.EmsEAiHourSumTab1OrgMapper;
import com.steerinfo.ems.emseaihoursumtab1org.model.EmsEAiHourSumTab1Org;
import com.steerinfo.ems.emsehistory.mapper.EmsEHistoryMapper;
import com.steerinfo.ems.emsehistory.model.EmsEHistory;
import com.steerinfo.ems.emsetiming.mapper.EmsETimingMapper;
import com.steerinfo.ems.emsetiming.model.EmsETiming;
import com.steerinfo.ems.emspaihoursumtab1.mapper.EmsPAiHourSumTab1Mapper;
import com.steerinfo.ems.emspaihoursumtab1.model.EmsPAiHourSumTab1;
import com.steerinfo.ems.emspaihoursumtab1org.mapper.EmsPAiHourSumTab1OrgMapper;
import com.steerinfo.ems.emspaihoursumtab1org.model.EmsPAiHourSumTab1Org;
import com.steerinfo.ems.emswaihoursumtab1.mapper.EmsWAiHourSumTab1Mapper;
import com.steerinfo.ems.emswaihoursumtab1.model.EmsWAiHourSumTab1;
import com.steerinfo.ems.emswaihoursumtab1org.mapper.EmsWAiHourSumTab1OrgMapper;
import com.steerinfo.ems.emswaihoursumtab1org.model.EmsWAiHourSumTab1Org;
import com.steerinfo.ems.formula.mapper.FormulaMapper;
import com.steerinfo.ems.trmcalpoint.mapper.TRmCalpointMapper;
import com.steerinfo.ems.trmcalpoint.model.TRmCalpoint;
import com.steerinfo.ems.trmcalpoint.service.ITRmCalpointService;
import com.steerinfo.ems.trmcalpointexvalue.model.TRmCalpointExValue;
import com.steerinfo.ems.trmcalpointexvalue.service.ITRmCalpointExValueService;
import com.steerinfo.ems.trmcalpointvalue.service.ITRmCalpointValueService;
import com.steerinfo.framework.mapper.IBaseMapper;
import com.steerinfo.framework.service.impl.BaseServiceImpl;
import com.steerinfo.framework.service.pagehelper.PageHelper;
import com.steerinfo.framework.service.pagehelper.PageList;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

/**
 * TRmCalpoint服务实现：
 * @author 王金涛
 * @version 1.0-SNAPSHORT 2019-10-11
 * 类描述
 * 修订历史：
 * 日期：2019-10-11
 * 作者：王金涛
 * 参考：
 * 描述：TRmCalpoint服务实现
 * @see null
 * @Copyright 湖南视拓信息技术股份有限公司. All rights reserved.
 */
@Service(value = "tRmCalpointService")
public class TRmCalpointServiceImpl extends BaseServiceImpl<TRmCalpoint, String> implements ITRmCalpointService {
	private static final Logger logger = LoggerFactory.getLogger(TRmCalpointServiceImpl.class);
	
	@Autowired
    private JdbcTemplate jdbcTemplate;
	
    @Autowired
    private TRmCalpointMapper tRmCalpointMapper;
    
    @Autowired
    private FormulaMapper formulaMapper;
    
    @Autowired
    ITRmCalpointValueService tRmCalpointValueService;
    
    @Autowired
    ITRmCalpointExValueService tRmCalpointExValueService;
    
    @Autowired
    EmsPAiHourSumTab1Mapper emsPAiHourSumTab1Mapper;
    
    @Autowired
    EmsPAiHourSumTab1OrgMapper emsPAiHourSumTab1OrgMapper;
    
    @Autowired
    EmsWAiHourSumTab1Mapper emsWAiHourSumTab1Mapper;
    
    @Autowired
    EmsWAiHourSumTab1OrgMapper emsWAiHourSumTab1OrgMapper;
    
    @Autowired
    private EmsEHistoryMapper emsEHistoryMapper;
    
    @Autowired
    private EmsETimingMapper emsETimingMapper;
    
    @Autowired
    private EmsEAiHourSumTab1OrgMapper emsEAiHourSumTab1OrgMapper;
    
    @Autowired
    private EmsEAiHourSumTab1Mapper emsEAiHourSumTab1Mapper;
    
    @Override
    protected IBaseMapper<TRmCalpoint, String> getMapper() {
        return tRmCalpointMapper;
    }

	@Override
	public List<Map> getRmCalpoint() {
		return tRmCalpointMapper.getRmCalpoint();
	}

	@Override
	synchronized public String getMaxId(String head){
        return this.tRmCalpointMapper.getMaxId(head);
    }
	
	@Override
	public List<Map<String, Object>> getRmCalpointVal(String clock, String clocke, String itemid, String datatype)  {
		String sql = "";
		String[] ids = itemid.split(",");
		List<Map<String, Object>> res = new ArrayList<Map<String, Object>>();
		Map<String, List<Map<String, Object>>> m = new HashMap<String, List<Map<String, Object>>>();
		for(int i=0; i<ids.length; i++){
			String id = ids[i];
			TRmCalpoint tRmCalpoint = tRmCalpointMapper.selectByPrimaryKey(id);
			String itemname = tRmCalpoint.getItemname();
			String tagTable = tRmCalpoint.getTagTable(); // 累计来源数据表
			String tagCol = tRmCalpoint.getTagCol(); // 累计来源数据列
			if (datatype.equalsIgnoreCase("sum")){
				sql = "select clock," + tagCol + " val from " + tagTable + " where clock>='" + clock +"' and clock <='" + clocke + "' order by clock";
				List<Map<String, Object>>  l = jdbcTemplate.queryForList(sql);
				m.put(id + "$" + itemname, l);
			} else if (datatype.equalsIgnoreCase("ontime")){
				List<Map<String, Object>> l = new ArrayList<Map<String, Object>>();
				sql = "select clock," + tagCol + " val from " + tagTable+"_org " + " where clock>='" + clock +"' and clock <='" + clocke + "' order by clock";
				l = jdbcTemplate.queryForList(sql);
				m.put(id + "$" + itemname, l);
			}
		}
		try {
			Date start = new SimpleDateFormat("yyyy-MM-dd HH").parse(clock);
			Date end = new SimpleDateFormat("yyyy-MM-dd HH").parse(clocke);
			while(!start.after(end)){
				Map<String, Object> md = new HashMap<String, Object>();
				md.put("tim", new SimpleDateFormat("yyyy-MM-dd HH").format(start));
				for (String str : m.keySet()) {
					for(Map<String, Object> map : m.get(str)){
						if (map!=null && map.get("clock").toString().equals(new SimpleDateFormat("yyyy-MM-dd HH").format(start))){
							Map<String, String> m1 = new HashMap<String, String>();
							m1.put("name", str.split("\\$")[1]);
							m1.put("val", map.get("val")==null?"":map.get("val").toString());
							md.put(str.split("\\$")[0], m1);
							break;
						}
					}
					if(md.get(str.split("\\$")[0]) == null){
						Map<String, String> mm = new HashMap<String, String>();
						mm.put("name", str.split("\\$")[1]);
						mm.put("val", "");
						md.put(str.split("\\$")[0], mm);
					}
				}
				res.add(md);
				start.setTime(start.getTime() + 3600 * 1000);
			}
		} catch (ParseException e) {
			e.printStackTrace();
			return null;
		}
		return res;
	}
	//十分钟查询
	@Override
	public List<Map<String, Object>> getRmCalpointValTim(String clock, String clocke, String itemid, String datatype)  {
		String sql = "";
		String[] ids = itemid.split(",");
		List<Map<String, Object>> res = new ArrayList<Map<String, Object>>();
		Map<String, List<Map<String, Object>>> m = new HashMap<String, List<Map<String, Object>>>();
		for (int i = 0; i < ids.length; i++) {
			String id = ids[i];
			TRmCalpoint tRmCalpoint = tRmCalpointMapper.selectByPrimaryKey(id);
			String itemname = tRmCalpoint.getItemname();
			String tagTable = tRmCalpoint.getBtype2(); // 十分钟来源数据表
			String energytypeid = tRmCalpoint.getEnergytypeid();
			String[] tens = tagTable.split("\\.");
			String tenTab = tens[0]; // 十分钟表
			String tagCol = tens[1]; // 十分钟字段
			if (datatype.equalsIgnoreCase("ontime")) {
				List<Map<String, Object>> l = new ArrayList<Map<String, Object>>();
				if (energytypeid.equalsIgnoreCase("E")) {
					sql = "select clock," + tagCol + " val from " + tenTab + " where clock >='" + clock
							+ "' and clock <='" + clocke + "' order by clock";
				} else {
					sql = "select to_char(tim, 'YYYY-MM-DD HH24:mi') clock," + tagCol + " val from " + tenTab
						+ " where to_char (tim, 'YYYY-MM-DD HH24:mi') >='" + clock
						+ "' and to_char (tim, 'YYYY-MM-DD HH24:mi') <='" + clocke + "' order by tim";
				}
				l = jdbcTemplate.queryForList(sql);
				m.put(id + "$" + itemname, l);
			}else {  //无累计值
				return null;
			}
		}
		try {
			Date start = new SimpleDateFormat("yyyy-MM-dd HH").parse(clock);
			Date end = new SimpleDateFormat("yyyy-MM-dd HH").parse(clocke);
			while (!start.after(end)) {
				Map<String, Object> md = new HashMap<String, Object>();
				md.put("tim", new SimpleDateFormat("yyyy-MM-dd HH:mm").format(start));
				for (String str : m.keySet()) {
					for (Map<String, Object> map : m.get(str)) {
						if (map != null && map.get("clock").toString()
								.equals(new SimpleDateFormat("yyyy-MM-dd HH:mm").format(start))) {
							Map<String, String> m1 = new HashMap<String, String>();
							m1.put("name", str.split("\\$")[1]);
							m1.put("val", map.get("val") == null ? "" : map.get("val").toString());
							md.put(str.split("\\$")[0], m1);
							break;
						}
					}
					if (md.get(str.split("\\$")[0]) == null) {
						Map<String, String> mm = new HashMap<String, String>();
						mm.put("name", str.split("\\$")[1]);
						mm.put("val", "");
						md.put(str.split("\\$")[0], mm);
					}
				}
				res.add(md);
				start.setTime(start.getTime() + 600 * 1000);
			}
		} catch (ParseException e) {
			e.printStackTrace();
			return null;
		}
		return res;
	}

	@Override
	public PageList<Map<String, Object>> getDate312ForPage(HashMap<String, Object> parmas, Integer pageNum, Integer pageSize) {
		PageHelper.startPage(pageNum, pageSize);
        List<Map<String, Object>> rows = tRmCalpointMapper.getDate312(parmas);
        PageList<Map<String, Object>> pageInfo = new PageList<Map<String, Object>>(rows);
        return pageInfo;
	}

	@Override
	public List<Map<String, Object>> getDate312ForChart(List<Map<String, Object>> list, int size) {
		List<Map<String, Object>> rl = new ArrayList<Map<String, Object>> ();
		for(Map<String, Object> m : list){
			if(m.get("clock")!=null && !m.get("clock").toString().isEmpty()){
				String clock = m.get("clock").toString();
				if(clock.startsWith("[")){
					JSONArray ja = JSONArray.parseArray(clock);
					m.put("clock", ja.get(0));
				}
			}else{
				return null;
			}
			String itemid = m.get("itemid").toString();
			// String timegranid = m.get("timegranid").toString();
			m.put("size", size);
			String itemname = tRmCalpointMapper.selectByPrimaryKey(itemid).getItemname();
			List<Map<String, Object>> l = tRmCalpointMapper.getDate312ForChart(m);
			Map<String, Object> mm = new HashMap<String, Object>();
			mm.put(itemid + "$" + itemname, l);
			rl.add(mm);
		}
		return rl;
	}

	@Override
    public TRmCalpoint updateNewItem(Map<String, Object> parmas){
    	tRmCalpointMapper.updateNewItem(parmas);
    	return tRmCalpointMapper.selectByPrimaryKey(parmas.get("itemid").toString());
	}

	@Override
	@Transactional(rollbackFor=Exception.class)
	public void delCalpoint(String[] ids) {
		logger.info("计量点维护表总共删除" + ids.length + "条数据");
		for (int i = 0; i < ids.length; i++) {
			logger.info("计量点维护表要删除的第" + (i + 1) + "条数据是" + getById(ids[i]).toString());
			formulaMapper.deleteBycode(ids[i]);
			this.delete(ids[i]);
			Map<String, Object> params = new HashMap<String, Object>();
			params.put("itemid", ids[i]);
			tRmCalpointValueService.deleteByParams(params);
		}
		logger.info("计量点维护表总共成功删除" + ids.length + "条数据");
	}

	@Override
	public List<Map<String, Object>> getInIdDate312(HashMap<String, Object> parmas) {
        List<Map<String, Object>> rows = tRmCalpointMapper.getInIdDate312(parmas);
        List<Map<String, Object>> pageInfo = new ArrayList<Map<String, Object>>(rows);
        return pageInfo;
	}

	@Override
	/**
	 *  动力、水小时表定时统计（自动补全24小时内的小时用量值）
	 */
	public void statHourData() {
		Map<String, Object> m = new HashMap<String, Object>();
		m.put("useflag", "1");
		m.put("itemtype", "AUTO");
		m.put("energytypeid", "'P','W'");
		List<TRmCalpoint> l = tRmCalpointMapper.selectLikeByParameters(m);
		int size = 0;
		if(l!=null && l.size()>0){
			size = l.size();
			Calendar cal = Calendar.getInstance();
			cal.add(Calendar.HOUR_OF_DAY, -2);
			// 2小时前
			String clock2 = new SimpleDateFormat("yyyy-MM-dd HH").format(cal.getTime());
			// 1小时前
			cal.add(Calendar.HOUR_OF_DAY, 1);
			String clock1 = new SimpleDateFormat("yyyy-MM-dd HH").format(cal.getTime());
			// 当前小时
			cal.add(Calendar.HOUR_OF_DAY, 1);
			String clock = new SimpleDateFormat("yyyy-MM-dd HH").format(cal.getTime());
			// 24小时前
			cal.add(Calendar.DAY_OF_YEAR, -1);
			String clock24 = new SimpleDateFormat("yyyy-MM-dd HH").format(cal.getTime());
			for(TRmCalpoint tc : l){
				// String source = tc.getSourceType(); // 数据源
				String itemid = tc.getItemid();
				String tag = tc.getTagCol(); // tag存储字段
				String table = tc.getTagTable(); // 存储表
				String tenvs=  tc.getBtype2(); // 十分钟表字段
				String r = this.restatHourData(itemid, clock);
				if(!r.isEmpty()){
					continue;
				}
				String[] tens = tenvs.split("\\.");
				String tenTab = tens[0];
				String tenCol = tens[1];
				try {
					// 补齐之前24小时的缺失的用量值
					String sql = "select max(clock) from "+table+" where clock<'"+clock1+"' and clock>'"+clock24+"' and "+tag+" is not null";
					// 上个记录时间
					String ck = jdbcTemplate.queryForObject(sql, String.class);
					if(ck==null || ck.isEmpty() || ck.equals(clock2)){
						continue;
					}else{
						// 上个已记录小时时间
						Date cls = new SimpleDateFormat("yyyy-MM-dd HH").parse(ck);
						String cksta = new SimpleDateFormat("yyyy-MM-dd HH:mm").format(cls);
						Date cle = new Date(cls.getTime() + 3600000l);
						String ckend = new SimpleDateFormat("yyyy-MM-dd HH:mm").format(cle);
						// 上个记录小时最后仪表值
						sql = "select val from "
								+ "(select " + tenCol + " val,row_number() over (order by tim desc) rn "
								+ "from " + tenTab + " where to_char(tim,'YYYY-MM-DD hh24:mi')>='"
								+ cksta
								+ "' and to_char(tim,'YYYY-MM-DD hh24:mi')<='"
								+ ckend +"') "
								+ "where rn = 1";
						BigDecimal hstrat = jdbcTemplate.queryForObject(sql, BigDecimal.class);
						// 水数据取整
						if(tc.getEnergytypeid().equalsIgnoreCase("W")){
							hstrat = hstrat.setScale(0, RoundingMode.DOWN);
						}
						// 当前小时开始仪表值
						sql = "select val from "
								+ "(select " + tenCol + " val,row_number() over (order by tim) rn "
								+ "from " + tenTab + " where to_char(tim,'YYYY-MM-DD hh24:mi')>='"
								+ clock1
								+ ":00' and to_char(tim,'YYYY-MM-DD hh24:mi')<='"
								+ clock +":00') "
								+ "where rn = 1";
						BigDecimal hend = jdbcTemplate.queryForObject(sql, BigDecimal.class);
						// 水数据取整
						if(tc.getEnergytypeid().equalsIgnoreCase("W")){
							hend = hend.setScale(0, RoundingMode.DOWN);
						}
						if(hend.doubleValue()>=hstrat.doubleValue()){
							Date nowh = new SimpleDateFormat("yyyy-MM-dd HH").parse(clock1);
							// 计算小时数
							Long hos = ((nowh.getTime() - cls.getTime())/3600000) - 1;
							// 总差值
							BigDecimal tval = hend.subtract(hstrat);
							// 计算小时用量值
							BigDecimal val = BigDecimal.ZERO; // 小时用量值
							BigDecimal last = BigDecimal.ZERO; // 最后一小时
							if(tc.getEnergytypeid().equalsIgnoreCase("W")){
								val = tval.divide(new BigDecimal(hos), 0, RoundingMode.DOWN);
								last = tval.subtract(val.multiply(new BigDecimal(hos-1))).setScale(0, RoundingMode.DOWN);
							}else{
								val = tval.divide(new BigDecimal(hos), 5, RoundingMode.HALF_UP);
								last = val;
							}
							while(cle.before(nowh)){
								// 用量值
								BigDecimal sval = val;
								// 需要补齐的clock
								String ckb = new SimpleDateFormat("yyyy-MM-dd HH").format(cle);
								// 最后1小时用量值(2小时间前)
								if(ckb.equals(clock2)){
									sval = last;
								}
								// 更新或者插入数据(小时用量值)
								if(table.equalsIgnoreCase("EMS_P_AI_HOUR_SUM_TAB1")){
									EmsPAiHourSumTab1 po = new EmsPAiHourSumTab1();
									po.setClock(ckb);
									po.setVal(sval.doubleValue(), tag);
									if(emsPAiHourSumTab1Mapper.updateByPrimaryKeySelective(po) == 0){
										po.setInsertTime(new Date());
										emsPAiHourSumTab1Mapper.insert(po);
									}
								}else{
									EmsWAiHourSumTab1 wo = new EmsWAiHourSumTab1();
									wo.setClock(ckb);
									wo.setVal(sval.doubleValue(), tag);
									if(emsWAiHourSumTab1Mapper.updateByPrimaryKeySelective(wo) == 0){
										wo.setInsertTime(new Date());
										emsWAiHourSumTab1Mapper.insert(wo);
									}
								}
								cle = new Date(cle.getTime() + 3600000l);
							}
							// 如果补齐了昨天数据，重新计算昨天日数据
							if(ckend.substring(0, 10).equals(clock24.substring(0, 10))){
								tRmCalpointValueService.restatCalpData(itemid, clock24.substring(0, 10), "DAY", "系统");
							}
						}
					}
				} catch(Exception e) {
					TRmCalpointExValue tce = new TRmCalpointExValue();
					tce.setItemid(itemid);
					tce.setExtype("6"); // 历史用量值更新失败
					tce.setClock(clock1);
					tce.setCreatetime(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
					tce.setBz("历史用量值更新失败，clock：" + clock1 + ",tag:" + tag + ",table:" + table);
					tRmCalpointExValueService.add(tce);
				}
			}
		}
		logger.info(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()) + " 动力、水小时表统计完毕,个数：" + size);
	}
	
	@Override
	/**
	 *  动力、水小时表定时统计（自动补全24小时内的小时用量值）
	 */
	public void statHourData(String clockstart, String clockend) {
		Map<String, Object> m = new HashMap<String, Object>();
		m.put("useflag", "1");
		m.put("itemtype", "AUTO");
		m.put("energytypeid", "'P','W'");
		List<TRmCalpoint> l = tRmCalpointMapper.selectLikeByParameters(m);
		int size = 0;
		if(l!=null && l.size()>0){
			size = l.size();
			Calendar cal = Calendar.getInstance();
			cal.add(Calendar.HOUR_OF_DAY, -2);
			// 2小时前
			String clock2 = new SimpleDateFormat("yyyy-MM-dd HH").format(cal.getTime());
			// 1小时前
			cal.add(Calendar.HOUR_OF_DAY, 1);
			String clock1 = new SimpleDateFormat("yyyy-MM-dd HH").format(cal.getTime());
			// 当前小时
			cal.add(Calendar.HOUR_OF_DAY, 1);
			String clock = new SimpleDateFormat("yyyy-MM-dd HH").format(cal.getTime());
			// 24小时前
			cal.add(Calendar.DAY_OF_YEAR, -1);
			String clock24 = new SimpleDateFormat("yyyy-MM-dd HH").format(cal.getTime());
			for(TRmCalpoint tc : l){
				// String source = tc.getSourceType(); // 数据源
				String itemid = tc.getItemid();
				String tag = tc.getTagCol(); // tag存储字段
				String table = tc.getTagTable(); // 存储表
				String tenvs=  tc.getBtype2(); // 十分钟表字段
				String r = this.restatHourData(itemid, clock);
				if(!r.isEmpty()){
					continue;
				}
				String[] tens = tenvs.split("\\.");
				String tenTab = tens[0];
				String tenCol = tens[1];
				try {
					// 补齐之前24小时的缺失的用量值
					String sql = "select max(clock) from "+table+" where clock<'"+clock1+"' and clock>'"+clock24+"' and "+tag+" is not null";
					// 上个记录时间
					String ck = jdbcTemplate.queryForObject(sql, String.class);
					if(ck==null || ck.isEmpty() || ck.equals(clock2)){
						continue;
					}else{
						// 上个已记录小时时间
						Date cls = new SimpleDateFormat("yyyy-MM-dd HH").parse(ck);
						String cksta = new SimpleDateFormat("yyyy-MM-dd HH:mm").format(cls);
						Date cle = new Date(cls.getTime() + 3600000l);
						String ckend = new SimpleDateFormat("yyyy-MM-dd HH:mm").format(cle);
						// 上个记录小时最后仪表值
						sql = "select val from "
								+ "(select " + tenCol + " val,row_number() over (order by tim desc) rn "
								+ "from " + tenTab + " where to_char(tim,'YYYY-MM-DD hh24:mi')>='"
								+ cksta
								+ "' and to_char(tim,'YYYY-MM-DD hh24:mi')<='"
								+ ckend +"') "
								+ "where rn = 1";
						BigDecimal hstrat = jdbcTemplate.queryForObject(sql, BigDecimal.class);
						// 水数据取整
						if(tc.getEnergytypeid().equalsIgnoreCase("W")){
							hstrat = hstrat.setScale(0, RoundingMode.DOWN);
						}
						// 当前小时开始仪表值
						sql = "select val from "
								+ "(select " + tenCol + " val,row_number() over (order by tim) rn "
								+ "from " + tenTab + " where to_char(tim,'YYYY-MM-DD hh24:mi')>='"
								+ clock1
								+ ":00' and to_char(tim,'YYYY-MM-DD hh24:mi')<='"
								+ clock +":00') "
								+ "where rn = 1";
						BigDecimal hend = jdbcTemplate.queryForObject(sql, BigDecimal.class);
						// 水数据取整
						if(tc.getEnergytypeid().equalsIgnoreCase("W")){
							hend = hend.setScale(0, RoundingMode.DOWN);
						}
						if(hend.doubleValue()>=hstrat.doubleValue()){
							Date nowh = new SimpleDateFormat("yyyy-MM-dd HH").parse(clock1);
							// 计算小时数
							Long hos = ((nowh.getTime() - cls.getTime())/3600000) - 1;
							// 总差值
							BigDecimal tval = hend.subtract(hstrat);
							// 计算小时用量值
							BigDecimal val = BigDecimal.ZERO; // 小时用量值
							BigDecimal last = BigDecimal.ZERO; // 最后一小时
							if(tc.getEnergytypeid().equalsIgnoreCase("W")){
								val = tval.divide(new BigDecimal(hos), 0, RoundingMode.DOWN);
								last = tval.subtract(val.multiply(new BigDecimal(hos-1))).setScale(0, RoundingMode.DOWN);
							}else{
								val = tval.divide(new BigDecimal(hos), 5, RoundingMode.HALF_UP);
								last = val;
							}
							while(cle.before(nowh)){
								// 用量值
								BigDecimal sval = val;
								// 需要补齐的clock
								String ckb = new SimpleDateFormat("yyyy-MM-dd HH").format(cle);
								// 最后1小时用量值(2小时间前)
								if(ckb.equals(clock2)){
									sval = last;
								}
								// 更新或者插入数据(小时用量值)
								if(table.equalsIgnoreCase("EMS_P_AI_HOUR_SUM_TAB1")){
									EmsPAiHourSumTab1 po = new EmsPAiHourSumTab1();
									po.setClock(ckb);
									po.setVal(sval.doubleValue(), tag);
									if(emsPAiHourSumTab1Mapper.updateByPrimaryKeySelective(po) == 0){
										po.setInsertTime(new Date());
										emsPAiHourSumTab1Mapper.insert(po);
									}
								}else{
									EmsWAiHourSumTab1 wo = new EmsWAiHourSumTab1();
									wo.setClock(ckb);
									wo.setVal(sval.doubleValue(), tag);
									if(emsWAiHourSumTab1Mapper.updateByPrimaryKeySelective(wo) == 0){
										wo.setInsertTime(new Date());
										emsWAiHourSumTab1Mapper.insert(wo);
									}
								}
								cle = new Date(cle.getTime() + 3600000l);
							}
							// 如果补齐了昨天数据，重新计算昨天日数据
							if(ckend.substring(0, 10).equals(clock24.substring(0, 10))){
								tRmCalpointValueService.restatCalpData(itemid, clock24.substring(0, 10), "DAY", "系统");
							}
						}
					}
				} catch(Exception e) {
					TRmCalpointExValue tce = new TRmCalpointExValue();
					tce.setItemid(itemid);
					tce.setExtype("6"); // 历史用量值更新失败
					tce.setClock(clock1);
					tce.setCreatetime(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
					tce.setBz("历史用量值更新失败，clock：" + clock1 + ",tag:" + tag + ",table:" + table);
					tRmCalpointExValueService.add(tce);
				}
			}
		}
		logger.info(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()) + " 动力、水小时表统计完毕,个数：" + size);
	}

	@Override
	public String restatHourData(String itemid, String clock) {
		TRmCalpoint tc = tRmCalpointMapper.selectByPrimaryKey(itemid);
		if(!tc.getUseflag().equals("1")){
			return "计量点已经被禁用";
		}
		if(!tc.getItemtype().equalsIgnoreCase("AUTO")){
			return "只计算自动采集计量点";
		}
		if(!tc.getEnergytypeid().equalsIgnoreCase("W") && !tc.getEnergytypeid().equalsIgnoreCase("P")){
			return "只计算水、动力计量点";
		}
		Date date = new Date();
		try {
			date = new SimpleDateFormat("yyyy-MM-dd HH").parse(clock);
		} catch (ParseException e) {
			return "日期格式错误";
		}
		Calendar cal = Calendar.getInstance();
		cal.setTime(date);
		cal.add(Calendar.HOUR_OF_DAY, -1);
		// 1小时前
		String clock1 = new SimpleDateFormat("yyyy-MM-dd HH").format(cal.getTime());
		// 获取配置
		String tag = tc.getTagCol(); // tag存储字段
		String table = tc.getTagTable(); // 存储表
		String tenvs=  tc.getBtype2(); // 十分钟表字段
		if(tag==null || table==null || tenvs==null || tag.trim().isEmpty() || table.trim().isEmpty() || tenvs.trim().isEmpty()){
			TRmCalpointExValue tce = new TRmCalpointExValue();
			tce.setItemid(itemid);
			tce.setExtype("2"); // 配置错误
			tce.setClock(clock);
			tce.setCreatetime(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
			tce.setBz("配置不能为空");
			tRmCalpointExValueService.add(tce);
			return "配置不能为空";
		}
		String[] tens = tenvs.split("\\.");
		if(tens.length!=2){
			TRmCalpointExValue tce = new TRmCalpointExValue();
			tce.setItemid(itemid);
			tce.setExtype("2"); // 配置错误
			tce.setClock(clock);
			tce.setCreatetime(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
			tce.setBz("十分钟表字段配置错误");
			tRmCalpointExValueService.add(tce);
			return "十分钟表字段配置错误";
		}
		String tenTab = tens[0];
		String tenCol = tens[1];
		String sql = "select " + tenCol + " val, to_char(tim,'YYYY-MM-DD HH24:MI:SS') tim from "
				+ tenTab
				+ " where " + tenCol + " is not null and to_char(tim, 'YYYY-MM-DD HH24:mi') >='" +  clock1+":00'"
				+ " and to_char(tim, 'YYYY-MM-DD HH24:mi')<='"  + clock+":00'"
				+ " order by tim ";
		List<Map<String, Object>>  lt = new ArrayList<Map<String, Object>>();
		try {
			lt = jdbcTemplate.queryForList(sql);
		}catch(Exception e) {
			TRmCalpointExValue tce = new TRmCalpointExValue();
			tce.setItemid(itemid);
			tce.setExtype("7"); // 十分钟数据错误
			tce.setClock(clock1);
			tce.setCreatetime(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
			tce.setBz("十分钟数据查询错误，clock：" + clock1 + ",col:" + tenCol + ",table:" + tenTab);
			tRmCalpointExValueService.add(tce);
			return "十分钟数据查询错误";
		}
		if(lt==null || lt.size()<1){
			TRmCalpointExValue tce = new TRmCalpointExValue();
			tce.setItemid(itemid);
			tce.setExtype("4"); // 十分钟数据不足以统计
			tce.setClock(clock1);
			tce.setCreatetime(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
			tce.setBz("十分钟数据不足以统计，clock：" + clock1 + ",col:" + tenCol + ",table:" + tenTab);
			tRmCalpointExValueService.add(tce);
			return "十分钟数据不足以统计";
		}else if(lt.size() == 1){
			TRmCalpointExValue tce = new TRmCalpointExValue();
			tce.setItemid(itemid);
			tce.setExtype("4"); // 十分钟数据不足以统计
			tce.setClock(clock1);
			tce.setCreatetime(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
			tce.setBz("十分钟数据不足以统计，clock：" + clock1 + ",col:" + tenCol + ",table:" + tenTab);
			tRmCalpointExValueService.add(tce);
			// 当前小时准点值
			sql = "select " + tenCol + " from " + tenTab + " where to_char(tim, 'YYYY-MM-DD HH24:mi') = '" + clock + ":00'";
			try {
				BigDecimal val = jdbcTemplate.queryForObject(sql, BigDecimal.class);
				// 水数据取整
				if(tc.getEnergytypeid().equalsIgnoreCase("W")){
					val = val.setScale(0, RoundingMode.DOWN);
				}
				if(table.equalsIgnoreCase("EMS_P_AI_HOUR_SUM_TAB1")){
					EmsPAiHourSumTab1Org po = new EmsPAiHourSumTab1Org();
					po.setClock(clock);
					po.setVal(val.doubleValue(), tag);
					if(emsPAiHourSumTab1OrgMapper.updateByPrimaryKeySelective(po) == 0){
						po.setInsertTime(new Date());
						emsPAiHourSumTab1OrgMapper.insert(po);
					}
				}else{
					EmsWAiHourSumTab1Org wo = new EmsWAiHourSumTab1Org();
					wo.setClock(clock);
					wo.setVal(val.doubleValue(), tag);
					if(emsWAiHourSumTab1OrgMapper.updateByPrimaryKeySelective(wo) == 0){
						wo.setInsertTime(new Date());
						emsWAiHourSumTab1OrgMapper.insert(wo);
					}
				}
			} catch(Exception e) {
				tce = new TRmCalpointExValue();
				tce.setItemid(itemid);
				tce.setExtype("3"); // 准点值错误
				tce.setClock(clock);
				tce.setCreatetime(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
				tce.setBz("准点值读取失败，clock：" + clock + ",col:" + tenCol + ",table:" + tenTab);
				tRmCalpointExValueService.add(tce);
				logger.error("准点数据查询失败，clock:" + clock);
			}
		}else{
			BigDecimal hval = BigDecimal.ZERO; // 小时用量值计算（十分钟累加）
			BigDecimal val1 = BigDecimal.ZERO; // 开始仪表值
			BigDecimal val2 = BigDecimal.ZERO; // 结束仪表值
			BigDecimal tenval = BigDecimal.ZERO; // 十分钟用量值
			try {
				for(int i=0;i<lt.size();i++){
					Map<String, Object> ma = lt.get(i);
					// 水数据取整
					if(tc.getEnergytypeid().equalsIgnoreCase("W")){
						val2 = new BigDecimal(ma.get("VAL").toString()).setScale(0, RoundingMode.DOWN);
					}else{
						val2 = new BigDecimal(ma.get("VAL").toString());
					}
					if(i==0){
						val1 = val2;
						continue;
					}
					tenval = val2.subtract(val1);
					// 水处理
					if(tc.getEnergytypeid().equalsIgnoreCase("W")){
						// 大于等于0
						if(tenval.doubleValue()>=0){
							if(tenval.doubleValue()>=500){ // 数据增加500以上，异常，当0处理
								// 记录异常数据
								TRmCalpointExValue tce = new TRmCalpointExValue();
								tce.setItemid(itemid);
								tce.setExtype("8"); // 十分钟水数据增大超过500
								tce.setBefvalue(val2);
								tce.setCurvalue(val1);
								tce.setClock(ma.get("TIM").toString());
								tce.setCreatetime(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
								tce.setBz("十分钟水数据增大超过500，clock：" + clock1 + ",col:" + tenCol + ",table:" + tenTab);
								tRmCalpointExValueService.add(tce);
							}else{
								hval = hval.add(tenval);
							}
						} else {
							// 清零处理
							if(tenval.doubleValue()<-20d && val2.doubleValue()<500d){
								hval = hval.add(val2);
							}
							// 记录异常数据
							TRmCalpointExValue tce = new TRmCalpointExValue();
							tce.setItemid(itemid);
							tce.setExtype("1"); // 十分钟数据变小
							tce.setBefvalue(val1);
							tce.setCurvalue(val2);
							tce.setClock(ma.get("TIM").toString());
							tce.setCreatetime(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
							tce.setBz("十分钟数据变小，clock：" + clock1 + ",col:" + tenCol + ",table:" + tenTab);
							tRmCalpointExValueService.add(tce);
						}
					}else{
						// 大于等于0
						if(tenval.doubleValue()>=0){
							hval = hval.add(tenval);
						} else {
							// 清零处理
							if(tenval.doubleValue()<-20d){
								hval = hval.add(val2);
							}
							// 记录异常数据
							TRmCalpointExValue tce = new TRmCalpointExValue();
							tce.setItemid(itemid);
							tce.setExtype("1"); // 十分钟数据变小
							tce.setBefvalue(val1);
							tce.setCurvalue(val2);
							tce.setClock(ma.get("TIM").toString());
							tce.setCreatetime(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
							tce.setBz("十分钟数据变小，clock：" + clock1 + ",col:" + tenCol + ",table:" + tenTab);
							tRmCalpointExValueService.add(tce);
						}
					}
					// 处理后值作为下一条数据的仪表初始值。
					val1 = val2;
				}
			}catch(Exception e) {
				return "小时用量值统计错误";
			}
			// 更新或者插入数据(小时用量值)
			if(table.equalsIgnoreCase("EMS_P_AI_HOUR_SUM_TAB1")){
				EmsPAiHourSumTab1 po = new EmsPAiHourSumTab1();
				po.setClock(clock1);
				po.setVal(hval.doubleValue(), tag);
				if(emsPAiHourSumTab1Mapper.updateByPrimaryKeySelective(po) == 0){
					po.setInsertTime(new Date());
					emsPAiHourSumTab1Mapper.insert(po);
				}
			}else{
				EmsWAiHourSumTab1 wo = new EmsWAiHourSumTab1();
				wo.setClock(clock1);
				wo.setVal(hval.doubleValue(), tag);
				if(emsWAiHourSumTab1Mapper.updateByPrimaryKeySelective(wo) == 0){
					wo.setInsertTime(new Date());
					emsWAiHourSumTab1Mapper.insert(wo);
				}
			}
			// 当前小时准点值
			sql = "select " + tenCol + " from " + tenTab + " where to_char(tim, 'YYYY-MM-DD HH24:mi') = '" + clock + ":00'";
			try {
				BigDecimal val = jdbcTemplate.queryForObject(sql, BigDecimal.class);
				// 水数据取整
				if(tc.getEnergytypeid().equalsIgnoreCase("W")){
					val = val.setScale(0, RoundingMode.DOWN);
				}
				if(table.equalsIgnoreCase("EMS_P_AI_HOUR_SUM_TAB1")){
					EmsPAiHourSumTab1Org po = new EmsPAiHourSumTab1Org();
					po.setClock(clock);
					po.setVal(val.doubleValue(), tag);
					if(emsPAiHourSumTab1OrgMapper.updateByPrimaryKeySelective(po) == 0){
						po.setInsertTime(new Date());
						emsPAiHourSumTab1OrgMapper.insert(po);
					}
				}else{
					EmsWAiHourSumTab1Org wo = new EmsWAiHourSumTab1Org();
					wo.setClock(clock);
					wo.setVal(val.doubleValue(), tag);
					if(emsWAiHourSumTab1OrgMapper.updateByPrimaryKeySelective(wo) == 0){
						wo.setInsertTime(new Date());
						emsWAiHourSumTab1OrgMapper.insert(wo);
					}
				}
			} catch(Exception e) {
				TRmCalpointExValue tce = new TRmCalpointExValue();
				tce.setItemid(itemid);
				tce.setExtype("3"); // 准点值错误
				tce.setClock(clock);
				tce.setCreatetime(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
				tce.setBz("准点值读取失败，clock：" + clock + ",col:" + tenCol + ",table:" + tenTab);
				tRmCalpointExValueService.add(tce);
				logger.error("准点数据查询失败，clock:" + clock);
			}
		}
		return "";
	}

	@Override
	public String restatHourDate(String itemid, String clock, String clockend) {
		Date start = new Date();
		Date end = new Date();
		String res = "";
		try {
			List<TRmCalpoint> l = null;
			Map<String, Object> m = null;
			if(itemid.equals("all")) {
				m = new HashMap<String, Object>();
				m.put("useflag", "1");
				m.put("itemtype", "AUTO");
				m.put("energytypeid", "'P','W'");
			}else {
				m = new HashMap<String, Object>();
				m.put("itemid", itemid);
			}
			l = tRmCalpointMapper.selectLikeByParameters(m);
			if(l.size() == 0) {
				return "计量点数据为空";
			}
			end = new SimpleDateFormat("yyyy-MM-dd HH").parse(clockend);
			for(TRmCalpoint tc : l){
				start = new SimpleDateFormat("yyyy-MM-dd HH").parse(clock);
				while(!start.after(end)){
					String r = this.restatHourData(tc.getItemid(), new SimpleDateFormat("yyyy-MM-dd HH").format(start));
					if (res.isEmpty() && r!=null){
						res = r;
					}
					start = new Date(start.getTime() + 3600*1000);
				}
			}
		} catch (ParseException e) {
			return "日期格式错误";
		}
		return res;
	}

	@Override
	public String restatHourDateE(String clock, String clockend) {
		Date start = new Date();
		Date end = new Date();
		String res = "";
		try {
			end = new SimpleDateFormat("yyyy-MM-dd HH").parse(clockend);
			start = new SimpleDateFormat("yyyy-MM-dd HH").parse(clock);
			while(!start.after(end)){
				String r = this.restatHourDataE(new SimpleDateFormat("yyyy-MM-dd HH").format(start));
				if (res.isEmpty() && r!=null){
					res = r;
				}
				start = new Date(start.getTime() + 3600*1000);
			}
		} catch (ParseException e) {
			return "日期格式错误";
		}
		return res;
	}


	@Override
	public String restatHourDataE(String clock) {
		Date date = new Date();
		try {
			// clock,  2021-04-22 09
			date = new SimpleDateFormat("yyyy-MM-dd HH").parse(clock);
		} catch (ParseException e) {
			return "日期格式错误";
		}
		Calendar cal = Calendar.getInstance();
		cal.setTime(date);
		cal.add(Calendar.HOUR_OF_DAY, -1);
		// 1小时前 2021-04-22 09
		String clock1 = new SimpleDateFormat("yyyy-MM-dd HH").format(cal.getTime());
		Map<String, Object> parmas = new HashMap<String, Object>();
		parmas.put("clock", clock + ":00:00");
		parmas.put("clocke", clock + ":09:00"); // 由于采集数据写入延迟，这里整点后9分钟内的算作整点的数据，比如2021/4/22 9:04:12 会当成 2021/4/22 9:00:00 的数据
		try {
			// 数据量太多，这里只要整点值
			List<EmsEHistory> ehList = emsEHistoryMapper.getEmsEHistoryByDate(parmas);
			if(ehList.size()>0){
				// 数据是否已经存在
				boolean exists = true;
		    	// 分钟clock - 2021-04-22 09:00
				String clockM = clock + ":00";
				EmsETiming e = emsETimingMapper.selectByPrimaryKey(clockM);
				if (e == null) {
					exists = false;
					e = new EmsETiming();
					e.setInsertTime(new Date());
					e.setClock(clockM);
				}
				for(EmsEHistory eeh:ehList){
					// 服务器-电开关号 例如：device/iec102-42-160/0637/totalpower
					String head = eeh.geteLine();
					if(head.split("/").length!=4){
						logger.error(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()) + "-数据格式错误-" + head);
						continue;
					}
					String line = "";
					if(head.split("/")[1].endsWith("13-200")){
						line = "1";
					}else if(head.split("/")[1].endsWith("56-201")){
						line = "2";
					}else if(head.split("/")[1].endsWith("56-202")){
						line = "3";
					}else if(head.split("/")[1].endsWith("32-158")){
						line = "4";
					}else if(head.split("/")[1].endsWith("42-158")){
						line = "5";
					}else if(head.split("/")[1].endsWith("42-159")){
						line = "6";
					}else if(head.split("/")[1].endsWith("42-160")){
						line = "7";
					}else{
						continue;
					}
					// 电开关号，例如： 0637
					String code = line + head.split("/")[2];
					// 数据 例如：{"感性无功":27.09,"容性无功":3.71,"正向有功":143.42,"反向有功":16.38}
					String eData = eeh.geteData();
					JSONObject jo = JSONObject.parseObject(eData);
					e.setVal(code, jo.getString("正向有功"), "f");
					e.setVal(code, jo.getString("反向有功"), "r");
				}
				// 更新
				if(exists){
					emsETimingMapper.updateByPrimaryKeySelective(e);
				}else{// 新增
					emsETimingMapper.insert(e);
				}
				// 从EMS_E_TIMING读取小时准点值-并且写入数据库
				Map<String, Object> mp = emsETimingMapper.getHourPointVal(clockM);
				// 整点数据 (clock)
				EmsEAiHourSumTab1Org eeho = new EmsEAiHourSumTab1Org();
				if(mp!=null && mp.size()>0){
					eeho.setClock(clock);
					eeho = EmsEAiUtil.setValByMap(eeho, mp);
	                int rs = emsEAiHourSumTab1OrgMapper.updateByPrimaryKeySelective(eeho);
	                if (rs == 0){
	                	eeho.setInsertTime(new Date());
	                	emsEAiHourSumTab1OrgMapper.insert(eeho);
	                }
	            }
				// 上一个小时
				EmsEAiHourSumTab1Org eeho1 = emsEAiHourSumTab1OrgMapper.selectByPrimaryKey(clock1);
				// 小时累计值 = 当前小时准点值 - 前1小时小时准点值
				if(eeho.getClock()==null || eeho.getClock().isEmpty() || eeho1==null || eeho1.getClock()==null || eeho1.getClock().isEmpty()){
					logger.error("数据表EMS_E_AI_HOUR_SUM_TAB1_ORG缺少数据：" + clock);
				} else {
					EmsEAiHourSumTab1 eeh = new EmsEAiHourSumTab1();
					eeh.setClock(clock1);
					eeh = EmsEAiUtil.setVal(eeh, eeho, eeho1);
					int rs = emsEAiHourSumTab1Mapper.updateByPrimaryKeySelective(eeh);
					if (rs == 0){
						eeh.setInsertTime(new Date());
	                	emsEAiHourSumTab1Mapper.insert(eeh);
	                }
				}
			}
		} catch (Exception e) {
			logger.error("重新生成单个小时的电表数据错误", e);
			return "重新计算单个小时的电表数据错误";
		}
		return null;
	}
}
