package org.objectweb.jonas_ejb.container;

import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Method;
import java.rmi.RemoteException;

import javax.ejb.EJBException;

import org.objectweb.util.monolog.api.BasicLevel;


public class JRepStatefulInputStream extends JStatefulInputStream {

    /**
     * Constructor.
     * @throws IOException
     */
    public JRepStatefulInputStream(InputStream in, JStatefulSwitch jss) throws IOException {
        super(in, jss);
    }

    /**
     * We must care about some object types.
     * @param obj serialized field
     * @return resolved object
     */
    protected Object resolveObject(Object obj) throws IOException {
        Object ret;
        if (obj instanceof JWrapper) {
            int type = ((JWrapper) obj).getType();
            switch (type) {
            /*case JWrapper.DATASOURCE:
                String dsname = (String) ((JWrapper) obj).getObject();
                ret = ConnectionManager.getConnectionManager(dsname);
                break;*/
            case JWrapper.LOCAL_ENTITY:
                TraceEjb.ssfpool.log(BasicLevel.DEBUG, "JEntityLocal");
                String jndiname = (String) ((JWrapper) obj).getObject();
                Object pk = ((JWrapper) obj).getPK();
                Object o = JLocalHome.getLocalHome(jndiname);
                ret = null;
                try {
                    ret = getFindByPKMethod(o.getClass(), pk.getClass()).invoke(o, (new Object[] {pk}) );
                } catch (Exception e) {                     
                    e.printStackTrace();
                }
                break;
            default:
                ret = super.resolveObject(obj);
                break;
            }
        } else if (obj instanceof JRepStatefulObjectId) {
            // Wrapper -> Local stateful
            // Recreate the bean in local
            JRepStatefulObjectId jrsoi = (JRepStatefulObjectId) obj;
            JRepStatefulLocalHome jrslh = (JRepStatefulLocalHome) JLocalHome.getLocalHome(jrsoi.getJndi());
            JRepStatefulLocal jrsl = null;

            JStatefulSwitch bs = null;
            JSessionFactory sf = (JSessionFactory) jrslh.getBeanFactory();

            try {
                bs = (JStatefulSwitch) sf.createEJB();
                JSessionContext bctx = sf.getJContext(bs);
                bs.bindICtx(null, (JStatefulContext) bctx);
                bctx.setState(2);
            } catch (javax.ejb.AccessLocalException e) {
                throw new EJBException("Security Exception thrown by an enterprise Bean", e);
            } catch (EJBException e) {
                throw e;
            } catch (RuntimeException e) {
                throw new EJBException("RuntimeException thrown by an enterprise Bean", e);
            } catch (Error e) {
                throw new EJBException("Error thrown by an enterprise Bean"+e);
            } catch (RemoteException e) {
                throw new EJBException("Remote Exception raised:", e);
            } 
            
            jrsl = (JRepStatefulLocal) bs.getLocal();
            jrsl.setClusterOId(jrsoi.getClusterOId());
            ret = jrsl;
        } else {
            ret = super.resolveObject(obj);
        }
        return ret;
    }

    private Method getFindByPKMethod(Class c, Class pk) {
    
        Method method = null;
        try {
            Method [] methods = c.getMethods();
            // Find first findByPrimaryKey method
            for (int i = 0; i < methods.length; i++) {
                if (methods[i].getName().equals("findByPrimaryKey")) {
                    method = methods[i];
                    break;
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        
        return method;
    }    
}
