package cn.net.cpzslibs.prot.handset;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.ConnectException;
import java.net.SocketTimeoutException;
import java.util.List;
import java.util.concurrent.TimeoutException;

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

public class Prot07Package extends ProtBase {
	private final short iTaskCode = 7;
	private final short iTaskCode_Car = 701;
	// 701号协议,要打的包标签已经是子标签。提示语：该追溯码已经被使用过了0xFFEB
	private final int LABEL_USED_701 = 0xFFEB;
	private PackageCallBack callBack;

	public interface PackageCallBack {
		public void updateData(boolean isSucess, long iPackage, long[] iChilds,
                               String errRet);
	}

	/**
	 * 701云南汽配模式打包，服务器将包标签的product_id=100进行一次激活操作<br/>
	 * 
	 * @author zwj<br/>
	 *         2015-5-2 下午10:24:02<br/>
	 * @param create
	 * @param packageId包标签
	 * @param childList
	 *            子标列表
	 * @param callBack
	 * @throws IOException
	 */
	public void dealCarPackage(SocketCreate create, Long packageId,
                               List<Long> childList, PackageCallBack callBack) throws IOException {
		this.iSendTaskIndex = create.getiTaskIndex();
		this.callBack = callBack;
		dealPackage(create.getDos(), create.getDis(), packageId, childList,
				iTaskCode_Car);

	}

	/**
	 * 7.普通模式模式打包<br/>
	 * 2014-10-31下午3:34:34<br/>
	 * dao.updateBychildId(iPackageId, iChildIds);<br/>
	 * mHandler -->ok返回的数据，obj为long[]数据，第0个数据为iPackage,余下的为iChildIds<br/>
	 * 
	 * @param create
	 * @param packageId
	 *            包标签
	 * @param childList
	 *            子标列表
	 * @throws IOException
	 */
	public void dealPackage(SocketCreate create, Long packageId,
                            List<Long> childList, PackageCallBack callBack) throws IOException {
		this.iSendTaskIndex = create.getiTaskIndex();
		this.callBack = callBack;
		dealPackage(create.getDos(), create.getDis(), packageId, childList,
				iTaskCode);

	}

	/**
	 * 7、打包操作<br/>
	 * 2015年3月24日13:20:21<br/>
	 * 传进来包和子的list，外层做一个package的for循环，然后每个package进行一次子查询<br/>
	 * mHandler -->ok返回的数据，obj为上传数量<br/>
	 * 
	 * @param dos
	 * @param dis
	 * @param packageId
	 *            包标签
	 * @param childList
	 *            子标列表
	 * @throws IOException
	 */
	private void dealPackage(DataOutputStream dos, DataInputStream dis,
			Long packageId, List<Long> childList, short iTaskCode)
			throws IOException {
		int updateMaxCount = 50;// 最大上传数量,服务器最大上传数量为100个
		long iPackageId = packageId;
		int childCount = childList.size();// 该包下的未上传的子标签数量
		// 判断该包中是否含有
		int yushu = childCount % updateMaxCount;
		int shang = childCount / updateMaxCount;
		long[] update_date = null;// 不超过最大限制的数量
		long[] update_Max_date = new long[updateMaxCount];// 上传最大数量的一个容器

		int endCount = 0;// 最后一个包的计数
		if (childCount <= updateMaxCount) {
			// 数据小于最大传送值的情况下，传送值就设置为包内子个数的
			update_date = new long[childCount];
			for (int j = 0; j < childCount; j++) {
				update_date[endCount++] = childList.get(j);
			}
			if (endCount == childCount) {
				if (recProt(dos, dis, iPackageId, update_date, iTaskCode)) {
					update_date = null;
				}
			}
		} else {
			update_date = new long[yushu];// 不超过最大限制的数量
			for (int j = 0; j < childCount; j++) {
				if ((j / updateMaxCount) < shang) {
					update_Max_date[endCount++] = childList.get(j);
					if (endCount == (updateMaxCount)) {
						// 上传最大量的数据100个
						if (recProt(dos, dis, iPackageId, update_Max_date,
								iTaskCode)) {
							endCount = 0;
							update_Max_date = null;
							update_Max_date = new long[updateMaxCount];
						}
					}
				} else {
					update_date[endCount++] = childList.get(j);
					if (endCount == yushu) {
						// 上传余下的数据
						if (recProt(dos, dis, iPackageId, update_date,
								iTaskCode)) {
							endCount = 0;
							update_date = null;
						}
					}
				}
			}
		}
	}

	/**
	 * 7、打包接收操作<br/>
	 * 2014-8-14下午1:55:55<br/>
	 * dao.updateBychildId(iPackageId, iChildIds);<br/>
	 * mHandler -->ok返回的数据，obj为iChildIds的数量
	 * 
	 * @param dos
	 * @param dis
	 * @param iPackageId
	 * @param iChildIds
	 * @return true:操作成功，false，失败
	 * @throws IOException
	 */
	private boolean recProt(DataOutputStream dos, DataInputStream dis,
			long iPackageId, long[] iChildIds, short iTaskCode)
			throws IOException {
		try {
			sendProt(dos, iPackageId, iChildIds, iTaskCode);
		} catch (TimeoutException e) {
			e.printStackTrace();
		}
		recHeader(dis);
		recFFFF(dis, iTaskCode);
		String ret = null;
		if (!isResult()) {
			ret = "打包异常(" + getiRecErrcode() + ")";
			if (getiRecErrcode() == LABEL_USED_701) {
				// 该追溯码已经被使用过了
				ret = "追溯码:" + iPackageId + "\n已经被使用过了";
			}
		}
		this.callBack.updateData(isSuccess(), iPackageId, iChildIds, ret);

		return isSuccess();
	}

	/**
	 * 7和701号协议
	 * 
	 * @param dos
	 * @param iPackageId
	 *            包标签
	 * @param iChildIds
	 *            子标签
	 * @throws IOException
	 */
	private void sendProt(DataOutputStream dos, long iPackageId,
			long[] iChildIds, short iTaskCode) throws IOException,
			SocketTimeoutException, TimeoutException, ConnectException {
		short bodySize = countBodySize(iPackageId, iChildIds);
		sendHeader(dos, iTaskCode, bodySize);
		sendiLabel(dos, iPackageId);
		for (int i = 0; i < iChildIds.length; i++) {
			sendiLabel(dos, iChildIds[i]);
		}
		sendCheckCode(dos);
	}

}
