/****************************************************************************
 * Copyright (C) 2012-2018 HS Coburg.
 * All rights reserved.
 * Contact: ecsec GmbH (info@ecsec.de)
 *
 * This file is part of the Open eCard App.
 *
 * GNU General Public License Usage
 * This file may be used under the terms of the GNU General Public
 * License version 3.0 as published by the Free Software Foundation
 * and appearing in the file LICENSE.GPL included in the packaging of
 * this file. Please review the following information to ensure the
 * GNU General Public License version 3.0 requirements will be met:
 * http://www.gnu.org/copyleft/gpl.html.
 *
 * Other Usage
 * Alternatively, this file may be used in accordance with the terms
 * and conditions contained in a signed written agreement between
 * you and ecsec GmbH.
 *
 ***************************************************************************/

package org.openecard.scio;

import java.io.IOException;
import java.nio.ByteBuffer;
import org.openecard.common.apdu.common.CardCommandAPDU;
import org.openecard.common.apdu.common.CardResponseAPDU;
import org.openecard.common.ifd.scio.SCIOCard;
import org.openecard.common.ifd.scio.SCIOChannel;
import org.openecard.common.ifd.scio.SCIOErrorCode;
import org.openecard.common.ifd.scio.SCIOException;


/**
 * NFC implementation of smartcardio's cardChannel interface.
 *
 * @author Dirk Petrautzki
 * @author Tobias Wich
 */
public class NFCCardChannel implements SCIOChannel {

    private final NFCCard card;

    public NFCCardChannel(NFCCard card) {
	this.card = card;
    }

    @Override
    public void close() throws SCIOException {
	// we only have one channel and this will be open as long as we are connected to the tag
    }

    @Override
    public SCIOCard getCard() {
	return card;
    }

    @Override
    public int getChannelNumber() {
	return 0;
    }

    @Override
    public CardResponseAPDU transmit(CardCommandAPDU apdu) throws SCIOException {
	return transmit(apdu.toByteArray());
    }

    @Override
    public CardResponseAPDU transmit(byte[] apdu) throws SCIOException {
	synchronized (card) {
	    try {
		return new CardResponseAPDU(card.transceive(apdu));
	    } catch (IOException ex) {
		if (! card.isCardPresent()) {
		    throw new SCIOException("Transmit of apdu command failed, because the card has already been removed.",
			    SCIOErrorCode.SCARD_W_REMOVED_CARD);
		} else {
		    // TODO: check if the error code can be chosen more specifically
		    throw new SCIOException("Transmit failed.", SCIOErrorCode.SCARD_F_UNKNOWN_ERROR, ex);
		}
	    }
	}
    }


    @Override
    public int transmit(ByteBuffer command, ByteBuffer response) throws SCIOException {
	CardResponseAPDU cra = transmit(command.array());
	byte[] data = cra.toByteArray();
	response.put(data);

	return data.length;
    }

    @Override
    public boolean isBasicChannel() {
	return true;
    }

    @Override
    public boolean isLogicalChannel() {
	return false;
    }

}

@@ -927,16 +927,53 @@
 .scio;%0A%0A
+import android.nfc.TagLostException;%0A
 import j
@@ -1336,16 +1336,73 @@
 eption;%0A
+import org.slf4j.Logger;%0Aimport org.slf4j.LoggerFactory;%0A
 %0A%0A/**%0A *
@@ -1572,16 +1572,102 @@
 nnel %7B%0A%0A
+    private static final Logger LOG = LoggerFactory.getLogger(NFCCardChannel.class);%0A%0A
     priv
@@ -2141,24 +2141,47 @@
 CIOException
+, IllegalStateException
  %7B%0A%09return t
@@ -2296,24 +2296,47 @@
 CIOException
+, IllegalStateException
  %7B%0A%09synchron
@@ -2414,16 +2414,201 @@
 apdu));%0A
+%09    %7D catch (TagLostException ex) %7B%0A%09%09LOG.debug(%22NFC Tag is not present.%22, ex);%0A%09%09throw new IllegalStateException(%22Transmit of apdu command failed, because the card is not present.%22);%0A
 %09    %7D c
@@ -2671,36 +2671,44 @@
 %09%09    throw new 
-SCIO
+IllegalState
 Exception(%22Trans
@@ -2760,16 +2760,8 @@
 has 
-already 
 been
@@ -2774,51 +2774,8 @@
 ed.%22
-,%0A%09%09%09    SCIOErrorCode.SCARD_W_REMOVED_CARD
 );%0A%09
@@ -3064,24 +3064,47 @@
 CIOException
+, IllegalStateException
  %7B%0A%09CardResp

Raise IllegalStateException as specified in case the NFC tag is not present anymore