package com.szpg.plc.message.response.read;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import com.szpg.db.data.PgSbStat;
import org.apache.commons.lang3.StringUtils;
import org.apache.log4j.Logger;

import com.szpg.db.dao.PgAlarmDao;
import com.szpg.db.dao.PgDeviceDao;
import com.szpg.db.dao.PgHjsbblDao;
import com.szpg.db.dao.PgSbDao;
import com.szpg.db.dao.impl.PgAlarmDaoImpl;
import com.szpg.db.dao.impl.PgDeviceDaoImpl;
import com.szpg.db.dao.impl.PgHjsbblDaoImpl;
import com.szpg.db.dao.impl.PgSbDaoImpl;
import com.szpg.db.data.PgAlarm;
import com.szpg.db.data.PgHjsbbl;
import com.szpg.plc.message.response.ReadMemoryCommandResponse;
import com.szpg.plc.util.ByteUtil;
import com.szpg.util.Configure;
import com.szpg.util.DataPushInterface;
import com.szpg.util.NumberFormat;
import com.szpg.util.TimeFormat;

public class ReadSbStatCommandResponse extends ReadMemoryCommandResponse {

	/**
	 * 
	 */
	private static final long serialVersionUID = -860746446736533413L;

	private final Logger logger = Logger.getLogger(this.getClass().getName());

	private List<Boolean> sb1Flt;
	private List<Boolean> sb2Flt;
	private List<Boolean> sb1Run;
	private List<Boolean> sb2Run;
	private String[] zcList; // 资产列表，从配置文件中获取

	public ReadSbStatCommandResponse() {
		sb1Flt = new ArrayList<Boolean>();
		sb2Flt = new ArrayList<Boolean>();
		sb1Run = new ArrayList<Boolean>();
		sb2Run = new ArrayList<Boolean>();
	}

	public List<Boolean> getSb1Flt() {
		return sb1Flt;
	}

	public void setSb1Flt(List<Boolean> sb1Flt) {
		this.sb1Flt = sb1Flt;
	}

	public List<Boolean> getSb2Flt() {
		return sb2Flt;
	}

	public void setSb2Flt(List<Boolean> sb2Flt) {
		this.sb2Flt = sb2Flt;
	}

	public List<Boolean> getSb1Run() {
		return sb1Run;
	}

	public void setSb1Run(List<Boolean> sb1Run) {
		this.sb1Run = sb1Run;
	}

	public List<Boolean> getSb2Run() {
		return sb2Run;
	}

	public void setSb2Run(List<Boolean> sb2Run) {
		this.sb2Run = sb2Run;
	}

	public String[] getZcList() {
		return zcList;
	}

	public void setZcList(String[] zcList) {
		this.zcList = zcList;
	}

	@Override
	public void afterAction() {
		// 1将水泵运行状态数据存入数据库
		PgSbDao sbDao = new PgSbDaoImpl();
		PgDeviceDao deviceDao = new PgDeviceDaoImpl();
		PgAlarmDao alarmDao = new PgAlarmDaoImpl();

		if (null != zcList && zcList.length > 0) {
			// 遍历设备列表，将水泵运行状态存入数据库
			for (int i = 0; i < zcList.length; i++) {
				String zcbh = zcList[i];

				int deviceId = deviceDao.findDeviceIdByCode(zcbh);
				if (deviceId > 0) {
					// 根据是否有数据来判断单泵还是双泵
					if (null == sb2Run.get(i)) {
						if (null != sb1Run.get(i)) {
							logger.info("水泵[" + zcbh + "][运行状态" + sb1Run.get(i) + "][故障报警" + sb1Flt.get(i) + "]");
							deviceDao.updateDeviceStatus(deviceId, sb1Run.get(i) == true ? "水泵运行" : "水泵停止");
						}
					} else {
						if (null != sb1Run.get(i)) {
							logger.info("水泵[" + zcbh + "][运行状态1" + sb1Run.get(i) + "][故障报警1" + sb1Flt.get(i) + "][运行状态2" + sb2Run.get(i) + "][故障报警2" + sb2Flt.get(i) + "]");
							deviceDao.updateDeviceStatus(deviceId, sb1Run.get(i) | sb2Run.get(i) == true ? "水泵运行" : "水泵停止");
						}
					}

					// 更新水泵状态现状表
					PgSbStat temp = sbDao.findLatestStatByDevice(deviceId);
					if (null == temp) {
						sbDao.addStatRecord(sb1Run.get(i), sb2Run.get(i), sb1Flt.get(i), sb2Flt.get(i), TimeFormat.formatTimestamp(this.getTime().getTime()), deviceId);
					} else {
						sbDao.updateStatRecord(sb1Run.get(i), sb2Run.get(i), sb1Flt.get(i), sb2Flt.get(i), TimeFormat.formatTimestamp(this.getTime().getTime()), deviceId);
					}
					
					// 如果单泵或者双泵有任意一个故障则都报警
					if ((null != sb1Flt.get(i) && sb1Flt.get(i) == true) || (null != sb2Flt.get(i) && sb2Flt.get(i) == true)) {
						PgAlarm alarm = new PgAlarm();
						alarm.setActive(1);
						alarm.setAlarm_date(this.getTime().getTime());
						alarm.setAlarmdevid(deviceId);
						alarm.setAlarmtypeid(PgAlarm.ALARM_TYPE_DEVRUN);
						alarm.setDescription("水泵故障");
						alarm.setUserid(null);
						
						alarmDao.insertAlarmRecord(alarm);
						deviceDao.updateDeviceStatus(deviceId, "水泵故障");
						
						// 将报警日志推送至市级平台
						String date = TimeFormat.formatDate(getTime().getTime());
						int count = alarmDao.findAlarmCountByDate(date);
						String bjbh = "THXC." + date + "." + NumberFormat.format(count+1, "0000");
						String bjms = alarm.getDescription();
						String bjsj = date.replace("-", "");
						String bjResp = DataPushInterface.addSBAlarmData(bjbh, zcbh, bjms, bjsj);
						logger.info("同步水泵故障报警记录日志结果：" + bjResp);
					}
				}
			}
		}
	}

	@Override
	public void parseData() {
		// 获取目标ACU的代码
		String acucode = this.getAcucode();
		byte[] messageData = this.getResponseData();
		
		logger.info("开始解析[读取水泵状态][" + acucode + "]指令响应");

		// 判断数据的长度是否满足要求
		if (messageData.length != Integer.parseInt(Configure.getProperty("acubl", acucode + ".SBSTAT.WORDCOUNT")) * 2) {
			logger.error("返回的数据长度与读取的不一致！");
			this.setValid(false);
			return;
		}

		// 将数据转换为字符串
		// 按照高字在前，低字在后；高字节在前，低字节在后的顺序
		String dataStr = "";
		for (int c = 0; c < messageData.length; c = c + 2) {
			dataStr = ByteUtil.binToBinString(new byte[] { messageData[c], messageData[c + 1] }) + dataStr;
		}

		PgHjsbblDao blDao = new PgHjsbblDaoImpl();

		// 获取目标ACU水泵运行状态内存区域的起始字地址
		int start = Integer.parseInt(Configure.getProperty("acubl", acucode + ".SBSTAT.START"));

		// 获取目标ACU水泵相关的资产列表，即水泵列表
		String zcListStr = Configure.getProperty("acubl", acucode + ".SB.ZC.LIST");
		if (StringUtils.isEmpty(zcListStr) == true) {
			this.setValid(false);
			return;
		}
		zcList = zcListStr.split(";");

		// 初始化结果集合
		sb1Run = Arrays.asList(new Boolean[zcList.length]);
		sb1Flt = Arrays.asList(new Boolean[zcList.length]);
		sb2Run = Arrays.asList(new Boolean[zcList.length]);
		sb2Flt = Arrays.asList(new Boolean[zcList.length]);

		// 解析水泵运行状态
		for (int i = 0; i < zcList.length; i++) {
			String zcbh = zcList[i];

			// 解析水泵1运行状态
			PgHjsbbl run1BlObj = blDao.findBlByBh(zcbh + ".Run1");
			if (null != run1BlObj) {
				int r1kszdz = run1BlObj.getKszdz(); // 开始字地址
				int r1offset = r1kszdz - start; // 与开始字的偏移量
				int r1bit = run1BlObj.getSzw(); // 所在位

				int indexRun1 = dataStr.length() - 1 - r1offset * 16 - r1bit;
				if (indexRun1 >= 0) {
					char run1Bt = dataStr.charAt(indexRun1); // 水泵1运行状态标志位
					getSb1Run().set(i, run1Bt == '1' ? true : false);
				}
			}

			// 解析水泵2运行状态
			PgHjsbbl run2BlObj = blDao.findBlByBh(zcbh + ".Run2");
			if (null != run2BlObj) {
				int r2kszdz = run2BlObj.getKszdz(); // 开始字地址
				int r2offset = r2kszdz - start; // 与开始字的偏移量
				int r2bit = run2BlObj.getSzw(); // 所在位

				int indexRun2 = dataStr.length() - 1 - r2offset * 16 - r2bit;
				if (indexRun2 >= 0) {
					char run2Bt = dataStr.charAt(indexRun2); // 水泵2运行状态标志位
					getSb2Run().set(i, run2Bt == '1' ? true : false);
				}
			}

			// 解析水泵1故障报警状态
			PgHjsbbl flt1BlObj = blDao.findBlByBh(zcbh + ".Flt1");
			if (null != flt1BlObj) {
				int f1kszdz = flt1BlObj.getKszdz(); // 开始字地址
				int f1offset = f1kszdz - start; // 与开始字的偏移量
				int f1bit = flt1BlObj.getSzw(); // 所在位

				int indexFlt1 = dataStr.length() - 1 - f1offset * 16 - f1bit;
				if (indexFlt1 >= 0) {
					char flt1Bt = dataStr.charAt(indexFlt1); // 水泵1故障报警标志位
					getSb1Flt().set(i, flt1Bt == '1' ? true : false);
				}
			}

			// 解析水泵2故障报警状态
			PgHjsbbl flt2BlObj = blDao.findBlByBh(zcbh + ".Flt2");
			if (null != flt2BlObj) {
				int f2kszdz = flt2BlObj.getKszdz(); // 开始字地址
				int f2offset = f2kszdz - start; // 与开始字的偏移量
				int f2bit = flt2BlObj.getSzw(); // 所在位

				int indexFlt2 = dataStr.length() - 1 - f2offset * 16 - f2bit;
				if (indexFlt2 >= 0) {
					char flt2Bt = dataStr.charAt(indexFlt2); // 水泵1故障报警标志位
					getSb2Flt().set(i, flt2Bt == '1' ? true : false);
				}
			}
		}
		
		logger.info("解析[读取水泵状态]响应指令结束");
	}

}
