package com.mq.mylibrary.rfid.io.service;

import android.app.Service;
import android.content.Intent;
import android.os.IBinder;

import com.fntech.Loger;
import com.mq.mylibrary.rfid.io.util.ArrayUtils;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.security.InvalidParameterException;
import java.util.ArrayList;
import java.util.List;

import android_serialport_api.SerialPort;

public class IOManager extends Service {
	private IRfidListener mRfidListener = null;
	private IBarcodeListener mBarcodeListener = null;

	public enum WORKMODE {
		NONE, RFID, BARCODE,
	};

	private WORKMODE mWorkMode = WORKMODE.NONE;

	public static IOManager INSTANCE = new IOManager();

	public void addRfidListener(IRfidListener listener,String device) {
		if (mRfidListener == null) {
		}
		mRfidListener = listener;
		mWorkMode = WORKMODE.RFID;

		initComm(device);
	}

	public void removeRfidListener() {
		mRfidListener = null;

		deInitComm();
	}

	public void addBarcodeListener(IBarcodeListener listener,String device) {
		if (mBarcodeListener == null) {

		}
		mBarcodeListener = listener;
		mWorkMode = WORKMODE.BARCODE;

		initComm(device);
	}

	public void removeBarcodeListener() {
		mBarcodeListener = null;
		deInitComm();
	}

	public IBinder onBind(Intent intent) {
		return null;
	}

	protected SerialPort mSerialPort = null;
	protected OutputStream mOutputStream = null;
	public InputStream mInputStream = null;

	byte[] mBuffer = null;
	int mBufferLength = 0;

	Thread mCommT = null;

	private boolean mCommExitFlag = true;

	private void initComm(String device) {
		if (mSerialPort == null) {
			try {
				mSerialPort = new SerialPort(new File(device), 115200,
						8);  //  /dev/ttySAC2       //, 0, 0  "/dev/ttyHSL1"
   
				mOutputStream = mSerialPort.getOutputStream();
				mInputStream = mSerialPort.getInputStream();

				// mCommT = new Thread(mCommDameo);
				// mCommT.start();
			} catch (SecurityException e) {
			} catch (IOException e) {
			} catch (InvalidParameterException e) {
			}
		}
	}

	private void deInitComm() {
		mCommExitFlag = true;

		if (mOutputStream != null) {
			try {
				mOutputStream.close();
			} catch (IOException ioe) {
			}

			mOutputStream = null;
		}

		if (mInputStream != null) {
			try {
				mInputStream.close();
			} catch (IOException ioe) {
			}
			mInputStream = null;
		}

		if (mSerialPort != null) {
			mSerialPort.close();
			mSerialPort = null;
		}
	}

	/*
	 * public void SendCmd(int iCmd, byte[] bData) throws FnIOException {
	 * 
	 * if ((mSerialPort == null) || (mInputStream == null) || (mOutputStream ==
	 * null)) { throw new FnIOException("comm not open"); }
	 * 
	 * try { mOutputStream.flush(); mOutputStream.write(bData, 0, bData.length);
	 * 
	 * Loger.disk_log("write", bData, "M10_H1"); } catch (java.io.IOException
	 * ioe) { } }
	 */

	public void SendCmd(byte[] bData, int len) throws FnIOException {

		if ((mSerialPort == null) || (mInputStream == null)
				|| (mOutputStream == null)) {
			throw new FnIOException("comm not open");
		}

		try {
			mOutputStream.write(bData, 0, len);
		} catch (IOException ioe) {
		}
	}

	public byte[] GetCommData() throws FnIOException, IOException {

		if ((mSerialPort == null) || (mInputStream == null)
				|| (mOutputStream == null)) {
			throw new FnIOException("comm not open");
		}

		int len = 0;
		int len_total = 0;
		byte[] byteReceiver = new byte[1024];
		List<byte[]> list = new ArrayList<byte[]>();
		while (true) {
			
			int iAvailable = 0; 
			iAvailable = mInputStream.available();
			if ((iAvailable == 0) || (iAvailable < 5)) {
				if (iAvailable > 0 && iAvailable < 5) {
					Loger.disk_log("read", "iAvailable>0 and < 5,=" + iAvailable,
							"M10_H1");
				}
				continue;
			}
			
			len = mInputStream.read(byteReceiver);
			Loger.disk_log("read", byteReceiver,len,"M10_H1");
			if (len > 0) {
				len_total += len;
				byte[] temp = ArrayUtils.copyArray(byteReceiver, 0, len);
				list.add(temp);
				byte[] last1 = list.get(list.size() - 1);
				byte[] last2 = null;
				if (list.size() > 1) {
					last2 = list.get(list.size() - 2);
				}
				if (last1.length >= 2) {
					if (last1[last1.length - 2] == 0x10
							&& last1[last1.length - 1] == 0x03) {
						Loger.disk_log("read", "break00000000","M10_H1");
						break;
					}
				} else if (last1.length == 1) {
					if (last1[last1.length - 1] == 0x03
							&& (last2 != null && last2[last2.length - 1] == 0x10)) {
						Loger.disk_log("read", "break1111111","M10_H1");
						break;
					}
				}
			}
		}// while (true)
		byte[] byteReturn = new byte[len_total];
		int pos = 0;
		for (byte[] item : list) {
			System.arraycopy(item, 0, byteReturn, pos, item.length);
			pos += item.length;
		}
		Loger.disk_log("read", byteReturn,"M10_H1");
		if (mBufferLength > 0) { 
			//mSerialPort.cleardata();
			return byteReturn; 
		}
		return byteReturn;
	}

	/*
	 * public byte[] GetCommData() throws FnIOException, IOException {
	 * 
	 * if ((mSerialPort == null) || (mInputStream == null) || (mOutputStream ==
	 * null)) { throw new FnIOException("comm not open"); }
	 * 
	 * Boolean flg = true; while (flg) { int iAvailable = 0; iAvailable =
	 * mInputStream.available();
	 * 
	 * if ((iAvailable == 0) || (iAvailable < 5)) { if (iAvailable > 0 &&
	 * iAvailable < 5) { Loger.disk_log("read", "iAvailable>0 and < 5,=" +
	 * iAvailable, "M10_H1"); } continue; }
	 * 
	 * if (iAvailable > 0) { mBuffer = new byte[iAvailable]; mBufferLength =
	 * mInputStream.read(mBuffer, 0, iAvailable); Loger.disk_log("read",
	 * mBuffer, "M10_H1");
	 * 
	 * if (mBufferLength > 0) { mSerialPort.cleardata(); return mBuffer; } } }
	 * return mBuffer; }
	 */

	String TAG_NAME = "RfidResponse";

	private void parseBarcodeResponse(byte[] bBuffer, int iLength) {
		BarcodePacket packet = new BarcodePacket(bBuffer, iLength);
		mBarcodeListener.onPacketIn(packet);
	}

	public static byte ISOTYPE_14443A = 'A';
	public static byte ISOTYPE_14443B = 'B';
	public static byte ISOTYPE_ICODE = '1';
	public static byte ANTENNA_ON = 1;
	public static byte ANTENNA_OFF = 0;
	public static byte CARD_ALL = 0x52;
	public static byte CARD_NOSLEEP = 0x26;

	public static byte AUTH_KEY_A = 0x60;
	public static byte AUTH_KEY_B = 0x61;

	public static final int PSAM_MIN = 1;
	public static final int PSAM_1 = 1;
	public static final int PSAM_2 = 2;
	public static final int PSAM_3 = 3;
	public static final int PSAM_4 = 4;
	public static final int PSAM_MAX = 4;

	public static final int PSAM_MODE_MIN = 1;
	public static final int PSAM_MODE_1 = 1;
	public static final int PSAM_MODE_2 = 2;
	public static final int PSAM_MODE_3 = 3;
	public static final int PSAM_MODE_4 = 4;
	public static final int PSAM_MODE_MAX = 4;

	private RfidPacket mPacket = new RfidPacket();

	public void pushRfidData(byte[] bBuffer, int iLength) {
		int iIndex = 0;
		while (iIndex < iLength) {
			mPacket.putByte(bBuffer[iIndex]);

			if (mPacket.isComplete()) {
				RfidPacket packet = new RfidPacket(mPacket);
				mRfidListener.onPacketIn(packet);
				mPacket.clean();
			}
			iIndex++;
		}
	}

	private Runnable mCommDameo = new Runnable() {
		public void run() {
			int iAvailable = 0;
			mCommExitFlag = false;
			try {
				while (!mCommExitFlag) {
					iAvailable = mInputStream.available();
					if (iAvailable > 0) {
						mBuffer = new byte[iAvailable];
						mBufferLength = mInputStream.read(mBuffer, 0,
								iAvailable);
						if (mBufferLength > 0) {
							if ((mWorkMode == WORKMODE.RFID)
									&& (mRfidListener != null)) {
								pushRfidData(mBuffer, mBufferLength);
							} else if ((mWorkMode == WORKMODE.BARCODE)
									&& (mBarcodeListener != null)) {
								parseBarcodeResponse(mBuffer, mBufferLength);
							}
						}
					}
					try {
						Thread.sleep(100);
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
				}
			} catch (IOException ioe) {
			}
		}
	};
}
