import Pcsc.*;
import AcsCommon.*;

public class ReaderFunctions {
	final static public int GET_SERIAL_EXPECTED_LENGTH = 2;

	public enum KEYTYPES {
		KEYTYPE_A(96), KEYTYPE_B(97);

		private int value;

		private KEYTYPES(int value) {
			this.value = value;
		}
	};

	private PcscReader pcscReader_;

	public PcscReader getPcscConnection() {
		return this.pcscReader_;
	}

	public void setPcscConnection(PcscReader pcscConnection) {
		this.pcscReader_ = pcscConnection;
	}

	public ReaderFunctions() {
		pcscReader_ = null;
	}

	public ReaderFunctions(PcscReader pcscReader) {
		setPcscConnection(pcscReader);
	}

	public void getSerialNumber() throws Exception {
		Apdu apdu = new Apdu();
		apdu.setCommand(new byte[] { (byte) 0xFF, (byte) 0xCA, (byte) 0x00, (byte) 0x00, (byte) 0x00 });
		apdu.setSendData(new byte[0]);
		apdu.setLengthExpected(GET_SERIAL_EXPECTED_LENGTH);

		getPcscConnection().sendApduCommand(apdu);

		if (apdu.getStatusWord()[0] != (byte) 0x90)
			throw new Exception(
					"[" + Helper.byteAsString(apdu.getStatusWord(), false) + "]" + " Get Serial Number failed");
	}

	public boolean loadAuthKey(byte keyNumber, byte[] key) throws Exception {
		Apdu apdu = new Apdu();

		if (keyNumber > 0x01)
			throw new Exception("Key number is invalid");

		if (key.length != 6)
			throw new Exception("Invalid key length");

		apdu.setCommand(new byte[] { (byte) 0xFF, (byte) 0x82, (byte) 0x00, (byte) keyNumber, (byte) 0x06 });
		apdu.setSendData(key);
		apdu.setLengthExpected((byte) 0x02);

		getPcscConnection().sendApduCommand(apdu);

		if (apdu.getStatusWord()[0] != (byte) 0x90)
			return false;

		return true;
	}

	public boolean authenticate(byte blockNum, KEYTYPES keyType, byte KeyNum) throws Exception {
		Apdu apdu = new Apdu();

		if (KeyNum > 0x20)
			throw new Exception("Key number is invalid");

		apdu.setCommand(new byte[] { (byte) 0xFF, (byte) 0x86, (byte) 0x00, (byte) 0x00, (byte) 0x05 });
		apdu.setSendData(new byte[] { (byte) 0x01, (byte) 0x00, (byte) blockNum, (byte) keyType.value, (byte) KeyNum });

		getPcscConnection().sendApduCommand(apdu);

		if (apdu.getStatusWord()[0] != (byte) 0x90)
			return false;

		return true;
	}
}
