package cn.net.cpzslibs.prot.handset;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.util.List;
import java.util.Map;

import cn.net.cpzslibs.prot.ProtBase;
import cn.net.cpzslibs.prot.SocketCreate;

public class Prot18Bind extends ProtBase {
	private final short iTaskCode18 = 18;// 一个一个传
	private final short iTaskCode_DisOrder1801 = 1801;// 无序
	private final short iTaskCode_Orderly1802 = 1802;// 有序
	private final short iTaskCodeRedWine1803 = 1803;// 红酒激活，无序
	private final short iTaskCodeRedWine1804 = 1804;// 红酒激活，有序
	private final short iTaskCode_Orderly1805 = 1805;// 手持机新加带生产者的
	private final int iMaxSendDisorderSize = 1000;// 无序
	public static final int iMaxSendOrderSize = 50000;// 有序

	/**
	 * 任务号1802：起始标签验证码错误，iTaskCode=0xFFE7
	 */
	public static final int BASE_18_START_ERR = 0xFFE7;
	/**
	 * 任务号1802：结束标签验证码错误，iTaskCode=0xFFE6
	 */
	public static final int BASE_18_END_ERR = 0xFFE6;
	/**
	 * 无序上行集合
	 */
	private long[] labels;
	/**
	 * 有序开始
	 */
	private long iStartL;
	/**
	 * 有序结束
	 */
	private long iEndL;

	/**
	 * 追溯码
	 */
	public final String kLabelId = "label_id";
	/**
	 * 产品日期
	 */
	public final String kProduceDate = "produce_date";
	/**
	 * 产品批号
	 */
	public final String kBatchNumber = "batch_number";
	/*-----------------1803特有的key--------------------------------*/
	/**
	 * 正品保证单id,1803使用
	 */
	public final String kGoodsId = "goodsId";

	/**
	 * 18.绑定,一个一个激活
	 * <p>
	 * 2014-12-30下午1:41:58
	 * </p>
	 * 
	 * @param dos
	 * @param dis
	 * @param iTaskCode
	 * @param iCompanyId公司ID
	 * @param iProductId产品ID
	 * @param iLabelId标签号
	 * @param iProduceDate生产日期
	 * @param iBatchNumber生产批号
	 * @return
	 * @throws IOException
	 */
	public boolean dealBind(SocketCreate create, long iProductId, long iLabelId, int iProduceDate, int iBatchNumber)
			throws IOException {
		return recProt(create.getDos(), create.getDis(), iTaskCode18, create.getiCompanyId(), iProductId, iLabelId,
				iProduceDate, iBatchNumber);
	}

	/**
	 * 1801.批量激活（无序标签）
	 * 
	 * @param dos
	 * @param dis
	 * @param iTaskCode
	 * @param iCompanyId企业ID
	 * @param iProductId
	 *            产品ID<br/>
	 *            根据产品id进行分批上传
	 * @param listSrc
	 *            标签号 <Map<String, Object>> long iLabelId,int iProduceDate,int
	 *            iBatchNumber
	 * @throws IOException
	 */
	public void dealProt1801(SocketCreate create, long iProductId, List<Map<String, Object>> listSrc, CallBack back)
			throws IOException {
		this.iBack = back;
		int listSrcSize = listSrc.size();
		int subs = listSrcSize / iMaxSendDisorderSize + (listSrcSize % iMaxSendDisorderSize > 0 ? 1 : 0);
		int end = iMaxSendDisorderSize;
		for (int i = 0; i < subs; i++) {
			List<Map<String, Object>> list = null;
			end = ((i == subs - 1) ? listSrc.size() : iMaxSendDisorderSize);
			list = listSrc.subList(0, end);
			long[] longs = new long[end];
			sendProt1801(create.getDos(), create.getiCompanyId(), iProductId, list, longs,listSrc);
			rectProt180_(create.getDis(), iTaskCode_DisOrder1801, longs);
		}
	}

	/**
	 * 1802：批量激活企业ID、产品ID和标签号（有序标签）
	 * 
	 * @param dos
	 * @param dis
	 * @param iTaskCode
	 * @param iCompanyId
	 * @param iProductId
	 * @param iStartLabelId
	 *            起始追溯码
	 * @param iEndLabelId
	 *            结束追溯码
	 * @param iProduceDate
	 * @param iBatchNumber
	 * @throws IOException
	 */
	public void dealProt1802(SocketCreate create, long iProductId, long iStartLabelId, long iEndLabelId,
                             int iProduceDate, int iBatchNumber, CallBack back) throws IOException {
		this.iBack = back;
		sendProt1802(create.getDos(), create.getiCompanyId(), iProductId, iStartLabelId, iEndLabelId, iProduceDate,
				iBatchNumber);
		long[] longs = { iStartLabelId, iEndLabelId };
		rectProt180_(create.getDis(), iTaskCode_Orderly1802, longs);
	}

	/**
	 * 1803.红酒批量激活（无序标签）
	 * 
	 * @param dos
	 * @param dis
	 * @param iTaskCode
	 * @param iCompanyId企业ID
	 * @param iProductId
	 *            产品ID<br/>
	 *            根据产品id进行分批上传
	 * @param listSrc
	 *            标签号 <Map<String, Object>> long iLabelId,long iGoodsId,int
	 *            iProduceDate,int iBatchNumber
	 * @throws IOException
	 */
	public void dealProt1803(SocketCreate create, long iProductId, List<Map<String, Object>> listSrc, CallBack back)
			throws IOException {
		this.iBack = back;
		int listSrcSize = listSrc.size();
		int subs = listSrcSize / iMaxSendDisorderSize + (listSrcSize % iMaxSendDisorderSize > 0 ? 1 : 0);
		int end = iMaxSendDisorderSize;
		for (int i = 0; i < subs; i++) {
			List<Map<String, Object>> list = null;
			end = ((i == subs - 1) ? listSrc.size() : iMaxSendDisorderSize);
			list = listSrc.subList(0, end);
			long[] longs = new long[end];
			sendProt1803(create.getDos(), create.getiCompanyId(), iProductId, list, longs);
			rectProt180_(create.getDis(), iTaskCodeRedWine1803, longs);
		}
	}

	/**
	 * 红酒城，有序批量激活 <br/>
	 * 2015-8-13下午2:20:46
	 * 
	 * @param create
	 * @param iProductId
	 * @param iStartLabelId
	 * @param iEndLabelId
	 * @param iProduceDate
	 * @param iBatchNumber
	 * @param iGoodsId
	 * @param back
	 * @throws IOException
	 */
	public void dealProt1804(SocketCreate create, long iProductId, long iStartLabelId, long iEndLabelId,
                             int iProduceDate, int iBatchNumber, long iGoodsId, CallBack back) throws IOException {
		this.iBack = back;
		sendProt1804(create.getDos(), create.getiCompanyId(), iProductId, iStartLabelId, iEndLabelId, iProduceDate,
				iBatchNumber, iGoodsId);
		long[] longs = { iStartLabelId, iEndLabelId };
		rectProt180_(create.getDis(), iTaskCodeRedWine1804, longs);
	}

	/**
	 * 1805：批量激活企业ID、产品ID和标签号（有序标签）新加生产者
	 * 
	 * @param dos
	 * @param dis
	 * @param iTaskCode
	 * @param iCompanyId
	 * @param iProductId
	 * @param iStartLabelId
	 *            起始追溯码
	 * @param iEndLabelId
	 *            结束追溯码
	 * @param iProduceDate
	 * @param iBatchNumber
	 * @throws IOException
	 * 
	 */
	public void dealProt1805(SocketCreate create, long iProductId, long iStartLabelId, long iEndLabelId,
                             int iProduceDate, int iBatchNumber, String scz, CallBack back) throws IOException {
		this.iBack = back;
		sendProt1805(create.getDos(), create.getiCompanyId(), iProductId, iStartLabelId, iEndLabelId, iProduceDate,
				iBatchNumber, scz);
		long[] longs = { iStartLabelId, iEndLabelId };
		rectProt180_(create.getDis(), iTaskCode_Orderly1805, longs);
	}

	/**
	 * 18.根据企业ID、产品ID和标签号作标签初次登记 标签已经存在，激活，服务器报错，错误码=1
	 * 
	 * @param dos
	 * @param dis
	 * @param iCompanyId
	 * @param iProductId
	 * @param iLabelId
	 * @return 错误已经处理
	 * @throws IOException
	 */
	private boolean recProt(DataOutputStream dos, DataInputStream dis, short iTaskCode, int iCompanyId, long iProductId,
			long iLabelId, int iProduceDate, int iBatchNumber) throws IOException {

		sendProt(dos, iTaskCode, iCompanyId, iProductId, iLabelId, iProduceDate, iBatchNumber);
		recHeader(dis);
		recFFFF(dis, iTaskCode);
		debugLog(iTaskCode, toStringFFFF());
		if (getiRecResult() == 0) {
			// TODO 正确
			// 绑定完成
			// sendMessage(CommonErrHandler.SYSTEM_18_BIND_OK, mHandler, 1);
			return true;
		} else {
			if (getiRecErrcode() == 1062) {
				// TODO 需要测试 Oracle为1，MySql为1062
				// 已经绑定过的标签，无法再次绑定
				// sendMessage(CommonErrHandler.SYSTEM_18_Already_BIND,
				// mHandler,
				// iLabelId);
			} else {
				// TODO 错误 服务器回馈的错误,标签和错误码
			}
			errLog(iTaskCode, getiRecErrcode());
		}
		return false;
	}

	/**
	 * 18. 根据企业ID、产品ID和标签号作标签初次登记 激活操作 2014-6-20下午2:42:10
	 * 
	 * @param dos
	 * @param iCompanyId公司ID
	 * @param iProductId产品ID
	 * @param iLabelId标签号
	 * @param iProduceDate生产日期
	 * @param iBatchNumber生产批号
	 * @throws IOException
	 */
	private void sendProt(DataOutputStream dos, short iTaskCode, int iCompanyId, long iProductId, long iLabel,
			int iProduceDate, int iBatchNumber) throws IOException {
		short bodySize = countBodySize(iCompanyId, iProductId, iLabel, iProduceDate, iBatchNumber);
		sendHeader(dos, iTaskCode, bodySize);
		// 发送公司标签
		sendiCompanyId(dos, iCompanyId);
		sendiProductId(dos, iProductId);
		sendiLabel(dos, iLabel);
		dos.writeInt(iProduceDate);
		dos.writeInt(iBatchNumber);
		sendCheckCode(dos);
	}

	/**
	 * 1803.发送协议<br/>
	 * 
	 * @param dos
	 * @param iCompanyId
	 *            公司id
	 * @param iProductId
	 *            产品id,根据产品id进行分类上传
	 * @param list
	 *            <Map<String, Object>> long iLabelId,long iGoodsId ,int
	 *            iProduceDate,int iBatchNumber
	 * @throws IOException
	 */
	private void sendProt1803(DataOutputStream dos, int iCompanyId, long iProductId, List<Map<String, Object>> list,
			long[] longs) throws IOException {
		int listSize = list.size();

		if (listSize > iMaxSendDisorderSize) {
			errLog(iTaskCodeRedWine1803, listSize + "无序批量上传发送超过限制" + iMaxSendDisorderSize);
			return;
		}
		if (listSize <= 0) {
			errLog(iTaskCodeRedWine1803, "无数据");
			return;
		}
		short iLabelNumber = (short) listSize;
		short bodySize = (short) (countBodySize(iCompanyId, iProductId, iLabelNumber) + listSize * (4 + 4 + 8 + 8));
		sendHeader(dos, iTaskCodeRedWine1803, bodySize);
		sendiCompanyId(dos, iCompanyId);
		sendiProductId(dos, iProductId);
		dos.writeShort(iLabelNumber);
		long label;
		for (int i = 0; i < listSize; i++) {
			Map<String, Object> map = list.get(i);
			label = (Long) map.get(kLabelId);
			longs[i] = label;
			sendiLabel(dos, label);
			dos.writeLong((Long) map.get(kGoodsId));
			dos.writeInt((Integer) map.get(kProduceDate));
			dos.writeInt((Integer) map.get(kBatchNumber));
			map.clear();
			map = null;
		}
		list.clear();
		list = null;
		sendCheckCode(dos);
	}

	/**
	 * 1802.发送协议
	 * 
	 * @param dos
	 * @param dis
	 * @param iTaskCode
	 * @param iCompanyId
	 * @param iProductId
	 * @param iStartLabelId
	 * @param iEndLabelId
	 * @param iProduceDate
	 * @param iBatchNumber
	 * @throws IOException
	 */
	private void sendProt1804(DataOutputStream dos, int iCompanyId, long iProductId, long iStartLabelId,
			long iEndLabelId, int iProduceDate, int iBatchNumber, long iGoodsId) throws IOException {
		if ((iEndLabelId / 10000 - iStartLabelId / 10000) > iMaxSendOrderSize) {
			errLog(iTaskCodeRedWine1804, "有序批量上传发送超过限制" + iMaxSendOrderSize);
			return;
		}
		short bodySize = countBodySize(iCompanyId, iProductId, iStartLabelId, iEndLabelId, iProduceDate, iBatchNumber,
				iGoodsId);
		sendHeader(dos, iTaskCodeRedWine1804, bodySize);
		sendiCompanyId(dos, iCompanyId);
		sendiProductId(dos, iProductId);
		dos.writeInt(iProduceDate);
		dos.writeInt(iBatchNumber);
		dos.writeLong(iGoodsId);
		sendiLabel(dos, iStartLabelId);
		sendiLabel(dos, iEndLabelId);
		sendCheckCode(dos);
	}

	/**
	 * 1801.发送协议
	 * 
	 * @param dos
	 * @param iCompanyId
	 * @param iProductId
	 * @param list
	 *            <Map<String, Object>> long iLabelId,int iProduceDate,int
	 *            iBatchNumber
	 * @throws IOException
	 */
	private void sendProt1801(DataOutputStream dos, int iCompanyId, long iProductId, List<Map<String, Object>> list,
			long[] longs,List<Map<String, Object>> listSrc) throws IOException {
		int listSize = list.size();
		if (listSize > iMaxSendDisorderSize) {
			errLog(iTaskCode_DisOrder1801, listSize + "无序批量上传发送超过限制" + iMaxSendDisorderSize);
			return;
		}
		if (listSize <= 0) {
			errLog(iTaskCode_DisOrder1801, "无数据");
			return;
		}
		/*for (int i = 0; i < listSize; i++) {
			System.out.println("开始发送数据:" + i + "   内容："+ list.get(i).get("test1"));
		}*/
		
		short iLabelNumber = (short) listSize;
		short bodySize = (short) (countBodySize(iCompanyId, iProductId, iLabelNumber) + listSize * (4 + 4 + 8));
		sendHeader(dos, iTaskCode_DisOrder1801, bodySize);
		sendiCompanyId(dos, iCompanyId);
		sendiProductId(dos, iProductId);
		dos.writeShort(iLabelNumber);
		long label;
		for (int i = 0; i < listSize; i++) {
			Map<String, Object> map = list.get(i);
			label = (Long) map.get(kLabelId);
			longs[i] = label;
			sendiLabel(dos, label);
			dos.writeInt((Integer) map.get(kProduceDate));
			dos.writeInt((Integer) map.get(kBatchNumber));
			map.clear();
			map = null;
		}
		list.clear();
		list = null;
		sendCheckCode(dos);

	}

	/**
	 * 1802.发送协议
	 * 
	 * @param dos
	 * @param dis
	 * @param iTaskCode
	 * @param iCompanyId
	 * @param iProductId
	 * @param iStartLabelId
	 * @param iEndLabelId
	 * @param iProduceDate
	 * @param iBatchNumber
	 * @throws IOException
	 */
	private void sendProt1802(DataOutputStream dos, int iCompanyId, long iProductId, long iStartLabelId,
			long iEndLabelId, int iProduceDate, int iBatchNumber) throws IOException {
		if ((iEndLabelId / 10000 - iStartLabelId / 10000) > iMaxSendOrderSize) {
			errLog(iTaskCode_Orderly1802, "有序批量上传发送超过限制" + iMaxSendOrderSize);
			return;
		}
		short bodySize = countBodySize(iCompanyId, iProductId, iStartLabelId, iEndLabelId, iProduceDate, iBatchNumber);
		sendHeader(dos, iTaskCode_Orderly1802, bodySize);
		sendiCompanyId(dos, iCompanyId);
		sendiProductId(dos, iProductId);
		dos.writeInt(iProduceDate);
		dos.writeInt(iBatchNumber);
		sendiLabel(dos, iStartLabelId);
		sendiLabel(dos, iEndLabelId);
		sendCheckCode(dos);
	}

	/**
	 * 1805.发送协议
	 * 
	 * @param dos
	 * @param dis
	 * @param iTaskCode
	 * @param iCompanyId
	 * @param iProductId
	 * @param iStartLabelId
	 * @param iEndLabelId
	 * @param iProduceDate
	 * @param iBatchNumber
	 * @throws IOException
	 */
	private void sendProt1805(DataOutputStream dos, int iCompanyId, long iProductId, long iStartLabelId,
			long iEndLabelId, int iProduceDate, int iBatchNumber, String scz) throws IOException {
		if ((iEndLabelId / 10000 - iStartLabelId / 10000) > iMaxSendOrderSize) {
			errLog(iTaskCode_Orderly1802, "有序批量上传发送超过限制" + iMaxSendOrderSize);
			return;
		}
		short sczlength = (short) scz.getBytes("UTF-8").length;

		short bodySize = (short) (countBodySize(iCompanyId, iProductId, iStartLabelId, iEndLabelId, iProduceDate,
				iBatchNumber, sczlength) + sczlength);

		sendHeader(dos, iTaskCode_Orderly1805, bodySize);
		sendiCompanyId(dos, iCompanyId);
		sendiProductId(dos, iProductId);
		dos.writeInt(iProduceDate);
		dos.writeInt(iBatchNumber);
		dos.writeShort(sczlength);
		dos.write(scz.getBytes("UTF-8"));
		sendiLabel(dos, iStartLabelId);
		sendiLabel(dos, iEndLabelId);

		sendCheckCode(dos);
	}

	/**
	 * 接收数据<br/>
	 * 
	 * @param dis
	 * @param iTaskCode
	 * @throws IOException
	 */
	private void rectProt180_(DataInputStream dis, short iTaskCode, long[] longs) throws IOException {
		recHeader(dis);
		System.out.println(getiRecTaskCode() + "--iTaskCode" + iTaskCode);
		if (isTaskCode(iTaskCode)) {
			int iFailedLabelNum = getUnsignedByte(dis.readShort());
			recCheckCode(dis);

			iBack.updateData(true, longs, null, 0, iFailedLabelNum);

		} else {

			recFFFF(dis, iTaskCode);
			debugLog(iTaskCode, toStringFFFF());
			if (isFFFF()) {
				errLog(iTaskCode, toStringFFFF());
				if (getiRecResult() == 1) {
					// 服务器错误返回错误码
					if (getiRecErrcode() == BASE_18_START_ERR) {
						iBack.updateData(false, longs, "请输入正确的起始追溯码", getiRecErrcode(), 0);
					} else if (getiRecErrcode() == BASE_18_END_ERR) {
						iBack.updateData(false, longs, "请输入正确的结束追溯码", getiRecErrcode(), 0);
					} else {
//						iBack.updateData(false, longs, "异常(" + getiRecErrcode() + ")", getiRecErrcode(), 0);
						iBack.updateData(false, longs, "存在重复的激活标签(" + getiRecErrcode() + ")", getiRecErrcode(), 0);
					}
				}
			} else {
				errLog(iTaskCode, "rec package err");
			}
		}
	}

	/**
	 * 上传了的数据<br>
	 * 正确和失败都对本地数据的修改
	 * <p>
	 * 2015-2-28上午11:09:58
	 * </p>
	 * 
	 * @return
	 */
	public long[] getLabels() {
		return labels;
	}

	/**
	 * 有序-起始标签
	 * <p>
	 * 2015-2-28上午11:35:42
	 * </p>
	 * 
	 * @return
	 */
	public long getiStartL() {
		return iStartL;
	}

	/**
	 * 有序-结束标签
	 * <p>
	 * 2015-2-28上午11:35:50
	 * </p>
	 * 
	 * @return
	 */
	public long getiEndL() {
		return iEndL;
	}

	private CallBack iBack;

	public interface CallBack {
		/**
		 * 
		 * <br/>
		 * 2015-5-5上午10:46:40
		 * 
		 * @param bool
		 *            是否成功
		 * @param labels
		 *            label数组
		 * @param errRet
		 *            错误信息提示(异常(错误码))
		 * @param iFailedNum
		 *            >0表示已经有标签被操作，=0正常
		 */
		public void updateData(boolean bool, long[] labels, String errRet, int iErrCode, int iFailedNum);
	}

}
