/*
 * Copyright 2005-2006 Sun Microsystems, Inc.  All Rights Reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
 * CA 95054 USA or visit www.sun.com if you need additional information or
 * have any questions.
 */


// common utility functions for the PC/SC tests

import javax.smartcardio.*;

import java.io.*;
import java.util.*;

public class Utils {

    static void setLibrary(String[] args) {
        if ((args.length > 0) && args[0].equalsIgnoreCase("MUSCLE")) {
            System.setProperty("sun.security.smartcardio.library", "/usr/local/$LIBISA/libpcsclite.so");
        }
    }

    static CardTerminal getTerminal(String[] args) throws Exception {
        setLibrary(args);

        TerminalFactory factory = TerminalFactory.getInstance("PC/SC", null);
        System.out.println(factory);

        List<CardTerminal> terminals = factory.terminals().list();
        System.out.println("Terminals: " + terminals);
        if (terminals.isEmpty()) {
            throw new Exception("No card terminals available");
        }
        CardTerminal terminal = terminals.get(0);

        if (terminal.isCardPresent() == false) {
            System.out.println("*** Insert card");
            if (terminal.waitForCardPresent(20 * 1000) == false) {
                throw new Exception("no card available");
            }
        }
        return terminal;
    }

    static final byte[] C1 = parse("00 A4 04 00 07 A0 00 00 00 62 81 01 00");
    static final byte[] R1a = parse("07 A0 00 00 00 62 81 01 04 01 00 00 24 05 00 0B 04 B0 25 90 00");
    static final byte[] R1b = parse("07 A0 00 00 00 62 81 01 04 01 00 00 24 05 00 0B 04 B0 55 90 00");

    static void transmitTestCommand(CardChannel channel) throws Exception {
        ResponseAPDU r = channel.transmit(new CommandAPDU(C1));
        byte[] rb = r.getBytes();
        if ((Arrays.equals(rb, R1a) == false) && (Arrays.equals(rb, R1b) == false)) {
            System.out.println("expected: " + toString(R1a));
            System.out.println("received: " + toString(rb));
            throw new Exception("Response does not match");
        }
    }

    private final static char[] hexDigits = "0123456789abcdef".toCharArray();

    public static String toString(byte[] b) {
        StringBuffer sb = new StringBuffer(b.length * 3);
        for (int i = 0; i < b.length; i++) {
            int k = b[i] & 0xff;
            if (i != 0) {
                sb.append(':');
            }
            sb.append(hexDigits[k >>> 4]);
            sb.append(hexDigits[k & 0xf]);
        }
        return sb.toString();
    }

    public static byte[] parse(String s) {
        try {
            int n = s.length();
            ByteArrayOutputStream out = new ByteArrayOutputStream(n >> 1);
            StringReader r = new StringReader(s);
            while (true) {
                int b1 = nextNibble(r);
                if (b1 < 0) {
                    break;
                }
                int b2 = nextNibble(r);
                if (b2 < 0) {
                    throw new RuntimeException("Invalid string " + s);
                }
                int b = (b1 << 4) | b2;
                out.write(b);
            }
            return out.toByteArray();
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    private static int nextNibble(StringReader r) throws IOException {
        while (true) {
            int ch = r.read();
            if (ch == -1) {
                return -1;
            } else if ((ch >= '0') && (ch <= '9')) {
                return ch - '0';
            } else if ((ch >= 'a') && (ch <= 'f')) {
                return ch - 'a' + 10;
            } else if ((ch >= 'A') && (ch <= 'F')) {
                return ch - 'A' + 10;
            }
        }
    }

}
