// BankClient.java

package org.objectweb.clusterDemo;

import java.util.Date;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.rmi.PortableRemoteObject;
import javax.transaction.UserTransaction;
import java.lang.Thread;

import org.objectweb.clusterDemo.*;

public class BankClient {

    private static final int m_MAXTHREADS = 100;

    private static int m_loops = 1;

    private static int m_clients = 1;

    private static void usage() {
        System.out.println("Usage: java org.objectweb.clusterDemo.BankClient <args>");
        System.out.println("  -l <loop>       number of loops per thread");
        System.out.println("  -c <client>     number of client threads");
        System.out.println("default args:");
        System.out.println(" -l " + m_loops + " -c " + m_clients);
    }

    public static void main(String args[]) {

        // Get command args
        for (int argn = 0; argn < args.length; argn++) {
            String s_arg = args[argn];
            Integer i_arg;
            if ((s_arg.equals("-l") == true)) {
                s_arg = args[++argn];
                i_arg = java.lang.Integer.valueOf(s_arg);
                m_loops = i_arg.intValue();
            } else if ((s_arg.equals("-c") == true)) {
                s_arg = args[++argn];
                i_arg = java.lang.Integer.valueOf(s_arg);
                m_clients = i_arg.intValue();
            } else if (s_arg.equals("-?") == true) {
                usage();
                System.exit(0);
            } else {
                usage();
                System.exit(2);
            }
        }

        // Check command args
        if (m_loops < 1) {
            usage();
            System.exit(2);
        }
        if (m_clients < 0) {
            usage();
            System.exit(2);
        }

        System.out.println("BankClient" + " -b " + m_loops + " -c " + m_clients);

        // Start pool of client threads
        BankClientThread t_thr[] = new BankClientThread[m_MAXTHREADS];
        long ttime[] = new long[m_MAXTHREADS];
        for (int p = 0; p < m_clients; p++) {
            t_thr[p] = new BankClientThread(m_loops);
            t_thr[p].start();
        }
        for (int p = 0; p < m_clients; p++) {
            try {
                t_thr[p].join();
                ttime[p] = t_thr[p].getTime();

            } catch (InterruptedException e) {
                System.out.println("ERROR: Problem in BankClientThread.join():\n" + e);
                System.exit(2);
            }
        }

        System.out.println("BankClient " + " -l " + m_loops + " -c " + m_clients);
        for (int p = 0; p < m_clients; p++) {
            System.out.println(" " + ttime[p]);
        }
        System.out.println("");
    }

}

class BankClientThread extends Thread {

    private int m_loops;

    private long m_time;

    private Integer m_accountId;

    public BankClientThread(int b) {
        m_loops = b;
    }

    public void run() {

        System.out.println("Running a BankClientThread...");
        BankSessionHome bsh;
        BankSession bs = null;

        Context initialContext = null;
        try {
            initialContext = new InitialContext();
            bsh = (BankSessionHome) initialContext.lookup("BankEJBBankSessionHome");
            bs = bsh.create();
        } catch (Exception e) {
            System.out.println("ERROR: Problem initializing :\n" + e);
            System.exit(2);
        }

        // Create a client account
        String clientName = "Client" + System.currentTimeMillis();
        try {
            m_accountId = bs.createAccount(clientName, 1000);
        } catch (Exception e) {
            System.out.println("ERROR: Problem creating Account :\n" + e);
            System.exit(2);
        }

        // Loop
        long d_begin = System.currentTimeMillis();

        System.out.println("Start loop");
        System.out.println("Each loop does 1 debit and 1 credit operations");

        for (int l = 0; l < m_loops; l++) {

            // Do one debit and one credit
            try {
                bs.debit(m_accountId, clientName, 100, "Retrait ATM");
                //sleep(1000);
                bs.credit(m_accountId, clientName, 100, "Depot ATM");
                //sleep(1000);

            } catch (Exception e) {
                System.out.println("ERROR: Problem during debit / credit phase :\n" + e);
                System.exit(2);
            }

            System.out.println("End of loop " + (l + 1) + " OK");
        }

        long d_end = System.currentTimeMillis();
        m_time = (d_end - d_begin) / (m_loops);
        //m_time = m_time - 2000;
        System.out.println("Time per transaction in millisec: " + m_time);
    }

    public long getTime() {
        return m_time;
    }
}
