package com.szpg.rmi;

import org.apache.log4j.Logger;
import org.apache.struts2.ServletActionContext;

import com.opensymphony.xwork2.ActionSupport;
import com.szpg.db.dao.PgAcuDao;
import com.szpg.db.dao.PgAlarmRuleDao;
import com.szpg.db.dao.PgDeviceDao;
import com.szpg.db.dao.PgHjsbblDao;
import com.szpg.db.dao.impl.PgAcuDaoImpl;
import com.szpg.db.dao.impl.PgAlarmRuleDaoImpl;
import com.szpg.db.dao.impl.PgDeviceDaoImpl;
import com.szpg.db.dao.impl.PgHjsbblDaoImpl;
import com.szpg.db.data.PgAcu;
import com.szpg.db.data.PgAlarmRule;
import com.szpg.db.data.PgHjsbbl;
import com.szpg.plc.message.AppMessageConstants;
import com.szpg.plc.message.command.ReadMemoryCommand;
import com.szpg.plc.message.command.WriteMemoryCommand;
import com.szpg.plc.message.command.write.SetSdThresholdWordCommand;
import com.szpg.plc.message.command.write.SetWdThresholdWordCommand;
import com.szpg.plc.protocol.fins.FINSConstants;
import com.szpg.plc.server.ACUClient;
import com.szpg.plc.server.ACUClientUtil;
import com.szpg.plc.util.ByteUtil;
import com.szpg.plc.util.Bytes;
import com.szpg.service.ReadSensorValueService;
import com.szpg.service.SetSensorThresholdService;
import com.szpg.util.Configure;
import com.szpg.util.NumberFormat;
import com.szpg.util.UnicodeConvertor;

import z.json.JSONObject;

public class RemoteWSCommandAction extends ActionSupport {

	/**
	 * 
	 */
	private static final long serialVersionUID = 2221187086461756012L;

	private String zcbh;
	
	private String wdThreshold;
	private String sdThreshold;
	
	private String format;
	private String jsoncallback;
	
	
	
	public String getZcbh() {
		return zcbh;
	}

	public void setZcbh(String zcbh) {
		this.zcbh = zcbh;
	}
	
	public String getWdThreshold() {
		return wdThreshold;
	}

	public void setWdThreshold(String wdThreshold) {
		this.wdThreshold = wdThreshold;
	}

	public String getSdThreshold() {
		return sdThreshold;
	}

	public void setSdThreshold(String sdThreshold) {
		this.sdThreshold = sdThreshold;
	}

	public String getFormat() {
		return format;
	}

	public void setFormat(String format) {
		this.format = format;
	}

	public String getJsoncallback() {
		return jsoncallback;
	}

	public void setJsoncallback(String jsoncallback) {
		this.jsoncallback = jsoncallback;
	}
	
	/**
	 * 读取温湿度实时监测值
	 * @return
	 * @throws Exception
	 */
	public String readWSValue() throws Exception {
		// 返回结果
		JSONObject jResult = new JSONObject();
		
		PgAcuDao acuDao = new PgAcuDaoImpl();
		
		if (null == zcbh || zcbh.equals("") == true) {
			jResult.put("success", false);
			jResult.put("code", "1");
			jResult.put("resaon", UnicodeConvertor.string2Unicode("资产编号为空"));
			
			returnToFront(jResult);
			return null;
		}
		
		String acucode = zcbh.substring(0, zcbh.indexOf(".", 6));
		PgAcu acu = acuDao.findACUByCode(acucode);
		if (null == acu) {
			jResult.put("success", false);
			jResult.put("code", "2");
			jResult.put("resaon", UnicodeConvertor.string2Unicode("未找到资产对应的PLC主机"));
			
			returnToFront(jResult);
			return null;
		}
		
		ACUClient client = ACUClientUtil.getInstance().getClients().get(acu.getAcu_host() + ":" + acu.getAcu_port());
		if (null != client) {
			ReadMemoryCommand command = ReadMemoryCommand.getInstance(AppMessageConstants.CMD_TYPE_READWSVALUE);
			// 二期设备发送查询温湿度及氧气指令
			if (client.getFlag().equals("23") || client.getFlag().equals("24")) {
				command = ReadMemoryCommand.getInstance(AppMessageConstants.CMD_TYPE_READWSYQVALUE);
			}
			String sour = Configure.getProperty("sys", "LOCALHOST.NET") + 
						  Configure.getProperty("sys", "LOCALHOST.NODE") + 
						  Configure.getProperty("sys", "LOCALHOST.UNIT");
			command.setMessageProducerId(sour);
			command.setMessageProducerHost(client.getHost());
			
			String dest = client.getNet() + client.getNode() + client.getUnit();
			
			command.setDestinationId(dest);
			
			command.setMemoryArea(FINSConstants.MEMORY_DM_AREA);
			
			try {
				// 没有找到对应的配置项，直接返回
				String start = "";
				String countWord = "";
				if (client.getFlag().equals("11")) {
					// 一期PLC配置
					start = Configure.getProperty("acubl", client.getAcucode() + ".WS.START");
					countWord = Configure.getProperty("acubl", client.getAcucode() + ".WS.WORDCOUNT");
				} else if (client.getFlag().equals("23") || client.getFlag().equals("24")) {
					// 二期PLC配置
					start = Configure.getProperty("acubl", client.getAcucode() + ".WSYQ.START");
					countWord = Configure.getProperty("acubl", client.getAcucode() + ".WSYQ.WORDCOUNT");
				}
				if (null == start || start.equals("")) {
					jResult.put("success", false);
					jResult.put("code", "4");
					jResult.put("resaon", UnicodeConvertor.string2Unicode("未找到对应的变量配置项"));

					returnToFront(jResult);
					return null;
				}
				
				// 设置读取的地址范围
				command.setStartAddress(ByteUtil.binToHexString(ByteUtil.intToBins(Integer.parseInt(start), 2)) + "00");
				command.setCountWord(Integer.parseInt(countWord));
				
				// 调用服务过程执行命令发送服务
				ReadSensorValueService service = new ReadSensorValueService();
				service.executeService(client, (ReadMemoryCommand) command);
				Logger.getLogger(this.getClass().getName()).info(command);
			} catch (Exception ex) {
				Logger.getLogger(getClass().getName()).error("发送查询温湿度指令异常" + ex);
			}
			
			jResult.put("success", true);
			jResult.put("resaon", UnicodeConvertor.string2Unicode("发送成功，请等待响应"));
			
			returnToFront(jResult);
			return null;
		} else {
			jResult.put("success", false);
			jResult.put("code", "3");
			jResult.put("resaon", UnicodeConvertor.string2Unicode("PLC主机不在线"));
			
			returnToFront(jResult);
			return null;
		}
	}
	
	/**
	 * 设置温度报警阈值
	 * @return
	 * @throws Exception
	 */
	public String setWdThreshold() throws Exception {
		// 返回结果
		JSONObject jResult = new JSONObject();
		
		PgAcuDao acuDao = new PgAcuDaoImpl();
		PgHjsbblDao blDao = new PgHjsbblDaoImpl();
		
		if (null == zcbh || zcbh.equals("") == true) {
			jResult.put("success", false);
			jResult.put("code", "1");
			jResult.put("resaon", UnicodeConvertor.string2Unicode("资产编号为空"));
			
			returnToFront(jResult);
			return null;
		}
		
		String acucode = zcbh.substring(0, zcbh.indexOf(".", 6));
		PgAcu acu = acuDao.findACUByCode(acucode);
		if (null == acu) {
			jResult.put("success", false);
			jResult.put("code", "2");
			jResult.put("resaon", UnicodeConvertor.string2Unicode("未找到资产对应的PLC主机"));
			
			returnToFront(jResult);
			return null;
		}
		
		ACUClient client = ACUClientUtil.getInstance().getClients().get(acu.getAcu_host() + ":" + acu.getAcu_port());
		if (null != client) {
			WriteMemoryCommand command = WriteMemoryCommand.getInstance(AppMessageConstants.CMD_TYPE_SETWDTHRESHOLD);
			
			// 源地址
			String sour = Configure.getProperty("sys", "LOCALHOST.NET") + 
						  Configure.getProperty("sys", "LOCALHOST.NODE") + 
						  Configure.getProperty("sys", "LOCALHOST.UNIT");
			
			// 目标地址
			String dest = client.getNet() + client.getNode() + client.getUnit();
			
			PgHjsbbl temBlObj = blDao.findBlByBh(zcbh + ".TemSet");
			if (null != temBlObj) {
				// SID在new对象的时候已经生成
				
				command.setMessageProducerId(sour);
				command.setMessageProducerHost(client.getHost());
				command.setDestinationId(dest);
				command.setMemoryArea(FINSConstants.MEMORY_WORK_AREA_WORD); //按字操作
				
				int start = temBlObj.getKszdz();
				int end = temBlObj.getJszdz();
				
				// 开始字地址
				command.setStartAddress(ByteUtil.binToHexString(ByteUtil.intToBins(start, 2)) + "00");
				
				// 字数
				int n = end - start + 1;
				command.setCount(n);
				
				// 字内容
				Bytes dataByte = SetSensorThresholdService.parseValueToBytes((float) NumberFormat.parseDouble(wdThreshold, "0.00"), n, client.getFlag());
				command.setValue( dataByte.toBytes() );
				((SetWdThresholdWordCommand) command).setThreshold(Float.parseFloat(wdThreshold));
				
				// 调用服务过程执行命令发送服务
				SetSensorThresholdService service = new SetSensorThresholdService();
				service.executeService(client, command);
				Logger.getLogger(this.getClass().getName()).info(command);
				
				jResult.put("success", true);
				jResult.put("resaon", UnicodeConvertor.string2Unicode("发送成功，请等待响应"));
				
				// 修改数据库中的报警阈值
				PgAlarmRuleDao ruleDao = new PgAlarmRuleDaoImpl();
				PgDeviceDao devDao = new PgDeviceDaoImpl();
				
				int deviceId = devDao.findDeviceIdByCode(zcbh);
				if (deviceId > 0) {
					PgAlarmRule rule = ruleDao.findRuleByDevice(deviceId);
					if (null != rule) {
						double sdHigh = 0.0;
						try {
							String highStr = rule.getHighvalue();
							if (null != highStr && highStr.isEmpty() == false && highStr.indexOf(";") > 0) {
								sdHigh = NumberFormat.parseDouble(highStr.split(";")[1], "0.00");
							}
							
							// 更新阈值
							ruleDao.updateWSHighThresholdByDevice(deviceId, NumberFormat.parseDouble(wdThreshold, "0.00"), sdHigh);
						} catch (Exception ex) {
							ex.printStackTrace();
						}
					}
				}
				
				returnToFront(jResult);
				return null;
			} else {
				jResult.put("success", false);
				jResult.put("code", "4");
				jResult.put("resaon", UnicodeConvertor.string2Unicode("未找到对应变量"));
				
				returnToFront(jResult);
				return null;
			}
		} else {
			jResult.put("success", false);
			jResult.put("code", "3");
			jResult.put("resaon", UnicodeConvertor.string2Unicode("PLC主机不在线"));
			
			returnToFront(jResult);
			return null;
		}
	}
	
	/**
	 * 设置湿度报警阈值
	 * @return
	 * @throws Exception
	 */
	public String setSdThreshold() throws Exception {
		// 返回结果
		JSONObject jResult = new JSONObject();
		
		PgAcuDao acuDao = new PgAcuDaoImpl();
		PgHjsbblDao blDao = new PgHjsbblDaoImpl();
		
		if (null == zcbh || zcbh.equals("") == true) {
			jResult.put("success", false);
			jResult.put("code", "1");
			jResult.put("resaon", UnicodeConvertor.string2Unicode("资产编号为空"));
			
			returnToFront(jResult);
			return null;
		}
		
		String acucode = zcbh.substring(0, zcbh.indexOf(".", 6));
		PgAcu acu = acuDao.findACUByCode(acucode);
		if (null == acu) {
			jResult.put("success", false);
			jResult.put("code", "2");
			jResult.put("resaon", UnicodeConvertor.string2Unicode("未找到资产对应的PLC主机"));
			
			returnToFront(jResult);
			return null;
		}
		
		ACUClient client = ACUClientUtil.getInstance().getClients().get(acu.getAcu_host() + ":" + acu.getAcu_port());
		if (null != client) {
			WriteMemoryCommand command = WriteMemoryCommand.getInstance(AppMessageConstants.CMD_TYPE_SETSDTHRESHOLD);
			
			// 源地址
			String sour = Configure.getProperty("sys", "LOCALHOST.NET") + 
						  Configure.getProperty("sys", "LOCALHOST.NODE") + 
						  Configure.getProperty("sys", "LOCALHOST.UNIT");
			
			// 目标地址
			String dest = client.getNet() + client.getNode() + client.getUnit();
			
			PgHjsbbl humBlObj = blDao.findBlByBh(zcbh + ".WetSet");
			if (null != humBlObj) {
				// SID在new对象的时候已经生成
				
				command.setMessageProducerId(sour);
				command.setMessageProducerHost(client.getHost());
				command.setDestinationId(dest);
				command.setMemoryArea(FINSConstants.MEMORY_WORK_AREA_WORD); // 按字操作
				
				int start = humBlObj.getKszdz();
				int end = humBlObj.getJszdz();
				
				// 开始字地址
				command.setStartAddress(ByteUtil.binToHexString(ByteUtil.intToBins(start, 2)) + "00");
				
				// 字数
				int n = end - start + 1;
				command.setCount(n);
				
				// 字内容
				Bytes dataByte = SetSensorThresholdService.parseValueToBytes((float) NumberFormat.parseDouble(sdThreshold, "0.00"), n, client.getFlag());
				command.setValue( dataByte.toBytes() );
				((SetSdThresholdWordCommand) command).setThreshold(Float.parseFloat(sdThreshold));
				
				// 调用服务过程执行命令发送服务
				SetSensorThresholdService service = new SetSensorThresholdService();
				service.executeService(client, command);
				Logger.getLogger(this.getClass().getName()).info(command);
				
				jResult.put("success", true);
				jResult.put("resaon", UnicodeConvertor.string2Unicode("发送成功，请等待响应"));
				
				// 修改数据库中的报警阈值
				PgAlarmRuleDao ruleDao = new PgAlarmRuleDaoImpl();
				PgDeviceDao devDao = new PgDeviceDaoImpl();
				
				int deviceId = devDao.findDeviceIdByCode(zcbh);
				if (deviceId > 0) {
					PgAlarmRule rule = ruleDao.findRuleByDevice(deviceId);
					if (null != rule) {
						double wdHigh = 0.0;
						try {
							String highStr = rule.getHighvalue();
							if (null != highStr && highStr.isEmpty() == false && highStr.indexOf(";") > 0) {
								wdHigh = NumberFormat.parseDouble(highStr.split(";")[0], "0.00");
							}
							
							// 更新阈值
							ruleDao.updateWSHighThresholdByDevice(deviceId, wdHigh, NumberFormat.parseDouble(sdThreshold, "0.00"));
						} catch (Exception ex) {
							ex.printStackTrace();
						}
					}
				}
				
				returnToFront(jResult);
				return null;
			} else {
				jResult.put("success", false);
				jResult.put("code", "4");
				jResult.put("resaon", UnicodeConvertor.string2Unicode("未找到对应变量"));
				
				returnToFront(jResult);
				return null;
			}
		} else {
			jResult.put("success", false);
			jResult.put("code", "3");
			jResult.put("resaon", UnicodeConvertor.string2Unicode("PLC主机不在线"));
			
			returnToFront(jResult);
			return null;
		}
	}
	
	
	/**
	 * 给前端返回
	 * @param jResult
	 * @throws Exception
	 */
	private void returnToFront(JSONObject jResult) throws Exception {
		// 返回jsonp格式的数据
		if (null != format && format.equalsIgnoreCase("jsonp") == true) {
			ServletActionContext.getResponse().getWriter().write(jsoncallback + "(" + jResult.toString() + ");");
		}

		ServletActionContext.getResponse().getWriter().write(jResult.toString());
	}
}
