package CardConnect;

import java.util.List;
import javax.smartcardio.Card;
import javax.smartcardio.CardChannel;
import javax.smartcardio.CardException; 
import javax.smartcardio.CardTerminal;
import javax.smartcardio.CommandAPDU;
import javax.smartcardio.ResponseAPDU;
import javax.smartcardio.TerminalFactory;


public class SendData {
    protected List<CardTerminal> terminals;
    protected TerminalFactory factory;
    private CardTerminal terminal;
    private Card card;
    private CardChannel channel;
    private ResponseAPDU rAPDU;

    SendData() {
        Init();
    }

    public void Init() {
        try 
    	{
            factory = TerminalFactory.getDefault();
            terminals = factory.terminals().list();
            // Get terminal for using to communication with card
            terminal = terminals.get(0);
            
            System.out.println("Terminals: " + terminals);
            System.out.println("Selected Terminal: " + terminal);

        }catch(Exception e){
            e.printStackTrace();
        }

        cardConnection();
    }

    private void cardConnection(){
        try {	
            while (!terminal.isCardPresent()){};
            card = terminal.connect("*");
            System.out.println("ATR: "+bytesToHex(card.getATR().getBytes()));
            channel = card.getBasicChannel();
            System.out.println("Card info: " + card+"\n");
        } catch (CardException ce){
            ce.printStackTrace();
        }
    }
    
    public ResponseAPDU SendRawData(CommandAPDU command) {
        try {
            long time_a = System.nanoTime();
            ResponseAPDU apduResponse = channel.transmit(command);
            long time_b = System.nanoTime();
            System.out.println("It took " + new Long(time_b - time_a) +
                    "nanoseconds to execute the APDU");
        } catch (CardException e) {
            e.printStackTrace();
            return null;
        }
        return null;
    }

    public ResponseAPDU SendRawData(byte[] payload){
        System.out.println("APDU request: " + bytesToHex(payload));
        try {
            long time_a = System.nanoTime();
            ResponseAPDU apduResponse = channel.transmit(new CommandAPDU(payload));
            long time_b = System.nanoTime();
            System.out.println("APDU response: " + bytesToHex(apduResponse.getBytes()));
            //System.out.printf("It took %.2f miliseconds to execute the APDU",
            //        double(time_b - time_a)/1000000);
            System.out.println("It took " + (new Long(time_b - time_a))/1000000 +
                    " milliseconds.\n");

            return apduResponse;
        } catch (CardException e) {
            e.printStackTrace();
            return null;
        }
    }

    public String bytesToHex(byte[] bytes) {

        char[] hexArray = "0123456789ABCDEF".toCharArray();
        char[] hexChars = new char[bytes.length * 2];
        
        for ( int j = 0; j < bytes.length; j++ ) {
            int v = bytes[j] & 0xFF;
            hexChars[j * 2] = hexArray[v >>> 4];
            hexChars[j * 2 + 1] = hexArray[v & 0x0F];
        }

        return new String(hexChars);
    }
    
}
