package org.objectweb.jonas.jtests.beans.relation.tier;

import javax.naming.NamingException;
import javax.naming.InitialContext;
import javax.rmi.PortableRemoteObject;
import java.security.SecureRandom;

import java.util.Hashtable;
import java.net.InetAddress;
import java.net.UnknownHostException;

/**
 * Utility class for TestFacade.
 */

public class TestFacadeUtil {

    private static String JNDI_NAME = "ejb/Test";

    // Home interface lookup methods

    /**
     * Obtain remote home interface from default initial context
     * @return Home interface for TestFacade. Lookup using JNDI_NAME
     */
    public static TestFacadeHome getHome() throws NamingException {
        // Obtain initial context
        InitialContext initialContext = new InitialContext();
        try {
            Object objRef = initialContext.lookup(JNDI_NAME);
            return (TestFacadeHome) PortableRemoteObject.narrow(objRef, TestFacadeHome.class);
        } finally {
            initialContext.close();
        }
    }

    /**
     * Obtain remote home interface from parameterised initial context
     * @param environment Parameters to use for creating initial context
     * @return Home interface for TestFacade. Lookup using JNDI_NAME
     */
    public static TestFacadeHome getHome(Hashtable environment) throws NamingException {
        // Obtain initial context
        InitialContext initialContext = new InitialContext(environment);
        try {
            Object objRef = initialContext.lookup(JNDI_NAME);
            return (TestFacadeHome) PortableRemoteObject.narrow(objRef, TestFacadeHome.class);
        } finally {
            initialContext.close();
        }
    }

    /** Cached per JVM server IP. */
    private static String hexServerIP = null;

    // initialise the secure random instance
    private static final SecureRandom seeder = new SecureRandom();

    /**
     * A 32 byte GUID generator (Globally Unique ID). These artificial keys
     * SHOULD <strong>NOT </strong> be seen by the user, not even touched by the
     * DBA but with very rare exceptions, just manipulated by the database and
     * the programs. Usage: Add an id field (type java.lang.String) to your EJB,
     * and add setId(XXXUtil.generateGUID(this)); to the ejbCreate method.
     */
    public static final String generateGUID(Object o) {
        StringBuffer tmpBuffer = new StringBuffer(16);
        if (hexServerIP == null) {
            InetAddress localInetAddress = null;
            try {
                // get the inet address
                localInetAddress = InetAddress.getLocalHost();
            } catch (UnknownHostException uhe) {
                System.err
                        .println("TestFacadeUtil: Could not get the local IP address using InetAddress.getLocalHost()!");
                // todo: find better way to get around this...
                uhe.printStackTrace();
                return null;
            }
            byte serverIP[] = localInetAddress.getAddress();
            hexServerIP = hexFormat(getInt(serverIP), 8);
        }
        String hashcode = hexFormat(System.identityHashCode(o), 8);
        tmpBuffer.append(hexServerIP);
        tmpBuffer.append(hashcode);

        long timeNow = System.currentTimeMillis();
        int timeLow = (int) timeNow & 0xFFFFFFFF;
        int node = seeder.nextInt();

        StringBuffer guid = new StringBuffer(32);
        guid.append(hexFormat(timeLow, 8));
        guid.append(tmpBuffer.toString());
        guid.append(hexFormat(node, 8));
        return guid.toString();
    }

    private static int getInt(byte bytes[]) {
        int i = 0;
        int j = 24;
        for (int k = 0; j >= 0; k++) {
            int l = bytes[k] & 0xff;
            i += l << j;
            j -= 8;
        }
        return i;
    }

    private static String hexFormat(int i, int j) {
        String s = Integer.toHexString(i);
        return padHex(s, j) + s;
    }

    private static String padHex(String s, int i) {
        StringBuffer tmpBuffer = new StringBuffer();
        if (s.length() < i) {
            for (int j = 0; j < i - s.length(); j++) {
                tmpBuffer.append('0');
            }
        }
        return tmpBuffer.toString();
    }

}