/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.apache.openejb.core.ivm;

import org.apache.openejb.ApplicationException;
import org.apache.openejb.BeanContext;
import org.apache.openejb.InterfaceType;
import org.apache.openejb.InvalidateReferenceException;
import org.apache.openejb.OpenEJBException;
import org.apache.openejb.OpenEJBRuntimeException;
import org.apache.openejb.ProxyInfo;
import org.apache.openejb.SystemException;
import org.apache.openejb.async.AsynchronousPool;
import org.apache.openejb.core.ServerFederation;
import org.apache.openejb.core.ThreadContext;
import org.apache.openejb.loader.SystemInstance;
import org.apache.openejb.spi.ApplicationServer;
import org.apache.openejb.spi.SecurityService;
import org.apache.openejb.util.LogCategory;
import org.apache.openejb.util.Logger;

import javax.ejb.AccessLocalException;
import javax.ejb.EJBAccessException;
import javax.ejb.EJBLocalObject;
import javax.ejb.EJBObject;
import java.io.ObjectStreamException;
import java.lang.reflect.Method;
import java.rmi.AccessException;
import java.rmi.RemoteException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Callable;

public abstract class EjbObjectProxyHandler extends BaseEjbProxyHandler {

    private static final Logger logger = Logger.getInstance(LogCategory.OPENEJB, "org.apache.openejb.util.resources");
    static final Map<String, Integer> dispatchTable;

    static {
        dispatchTable = new HashMap<String, Integer>();
        dispatchTable.put("getHandle", 1);
        dispatchTable.put("getPrimaryKey", 2);
        dispatchTable.put("isIdentical", 3);
        dispatchTable.put("remove", 4);
        dispatchTable.put("getEJBHome", 5);
        dispatchTable.put("getEJBLocalHome", 6);
    }

    public EjbObjectProxyHandler(final BeanContext beanContext, final Object pk, final InterfaceType interfaceType, final List<Class> interfaces, final Class mainInterface) {
        super(beanContext, pk, interfaceType, interfaces, mainInterface);
    }

    public abstract Object getRegistryId();

    @Override
    public Object _invoke(final Object p, final Class interfce, final Method m, final Object[] a) throws Throwable {
        Object retValue = null;
        Throwable exc = null;

        final String methodName = m.getName();
        try {
            if (logger.isDebugEnabled()) {
                logger.debug("EjbObjectProxyHandler: invoking method " + methodName + " on " + deploymentID + " with identity " + primaryKey);
            }
            Integer operation = dispatchTable.get(methodName);
            if (operation != null) {
                if (operation == 3) {
                    if (m.getParameterTypes()[0] != EJBObject.class && m.getParameterTypes()[0] != EJBLocalObject.class) {
                        operation = null;
                    }
                } else {
                    operation = m.getParameterTypes().length == 0 ? operation : null;
                }
            }
            if (operation == null || !interfaceType.isComponent()) {
                retValue = businessMethod(interfce, m, a, p);
            } else {
                switch (operation) {
                    case 1:
                        retValue = getHandle(m, a, p);
                        break;
                    case 2:
                        retValue = getPrimaryKey(m, a, p);
                        break;
                    case 3:
                        retValue = isIdentical(m, a, p);
                        break;
                    case 4:
                        retValue = remove(interfce, m, a, p);
                        break;
                    case 5:
                        retValue = getEJBHome(m, a, p);
                        break;
                    case 6:
                        retValue = getEJBLocalHome(m, a, p);
                        break;
                    default:
                        throw new OpenEJBRuntimeException("Inconsistent internal state");
                }
            }

            return retValue;

            /*
            * The ire is thrown by the container system and propagated by
            * the server to the stub.
            */
        } catch (final InvalidateReferenceException ire) {
            invalidateAllHandlers(getRegistryId());
            exc = ire.getRootCause() != null ? ire.getRootCause() : new RemoteException("InvalidateReferenceException: " + ire);
            throw exc;
            /*
            * Application exceptions must be reported dirctly to the client. They
            * do not impact the viability of the proxy.
            */
        } catch (final ApplicationException ae) {
            exc = ae.getRootCause() != null ? ae.getRootCause() : ae;
            if (exc instanceof EJBAccessException) {
                if (interfaceType.isBusiness()) {
                    throw exc;
                } else {
                    if (interfaceType.isLocal()) {
                        throw new AccessLocalException(exc.getMessage()).initCause(exc.getCause());
                    } else {
                        throw new AccessException(exc.getMessage());
                    }
                }

            }
            throw exc;

            /*
            * A system exception would be highly unusual and would indicate a sever
            * problem with the container system.
            */
        } catch (final SystemException se) {
            try {
                invalidateReference();
            } catch (final IllegalStateException ignore) {
                logger.debug("Tried to invalidate reference before processing system error: " +ignore.getMessage());
            }
            exc = se.getRootCause() != null ? se.getRootCause() : se;
            logger.debug("The container received an unexpected exception: ", exc);
            throw new RemoteException("Container has suffered a SystemException", exc);
        } catch (final OpenEJBException oe) {
            exc = oe.getRootCause() != null ? oe.getRootCause() : oe;
            logger.debug("The container received an unexpected exception: ", exc);
            throw new RemoteException("Unknown Container Exception", oe.getRootCause());
        } finally {
            if (logger.isDebugEnabled()) {
                if (exc == null) {
                    String ret = "void";
                    if (null != retValue) {
                        try {
                            ret = retValue.toString();
                        } catch (final Exception e) {
                            ret = "toString() failed on (" + e.getMessage() + ")";
                        }
                    }
                    logger.debug("EjbObjectProxyHandler: finished invoking method " + methodName + ". Return value:" + ret);
                } else {
                    logger.debug("EjbObjectProxyHandler: finished invoking method " + methodName + " with exception " + exc);
                }
            }
        }
    }

    protected Object getEJBHome(final Method method, final Object[] args, final Object proxy) throws Throwable {
        checkAuthorization(method);
        return getBeanContext().getEJBHome();
    }

    protected Object getEJBLocalHome(final Method method, final Object[] args, final Object proxy) throws Throwable {
        checkAuthorization(method);
        return getBeanContext().getEJBLocalHome();
    }

    protected Object getHandle(final Method method, final Object[] args, final Object proxy) throws Throwable {
        checkAuthorization(method);
        return new IntraVmHandle(proxy);
    }

    @Override
    public ProxyInfo getProxyInfo() {
        return new ProxyInfo(getBeanContext(), primaryKey, getInterfaces(), interfaceType, getMainInterface());
    }

    @Override
    protected Object _writeReplace(final Object proxy) throws ObjectStreamException {
        /*
         * If the proxy is being  copied between bean instances in a RPC
         * call we use the IntraVmArtifact
         */
        if (IntraVmCopyMonitor.isIntraVmCopyOperation()) {
            return new IntraVmArtifact(proxy);
            /*
            * If the proxy is referenced by a stateful bean that is  being
            * passivated by the container we allow this object to be serialized.
            */
        } else if (IntraVmCopyMonitor.isStatefulPassivationOperation()) {
            return proxy;
            /*
            * If the proxy is being copied between class loaders
            * we allow this object to be serialized.
            */
        } else if (IntraVmCopyMonitor.isCrossClassLoaderOperation()) {
            return proxy;
            /*
            * If the proxy is serialized outside the core container system,
            * we allow the application server to handle it.
            */
        } else if (!interfaceType.isRemote()) {

            return proxy;

        } else {
            final ApplicationServer applicationServer = ServerFederation.getApplicationServer();
            if (interfaceType.isBusiness()) {
                return applicationServer.getBusinessObject(this.getProxyInfo());
            } else {
                return applicationServer.getEJBObject(this.getProxyInfo());
            }
        }
    }

    protected abstract Object getPrimaryKey(Method method, Object[] args, Object proxy) throws Throwable;

    protected abstract Object isIdentical(Method method, Object[] args, Object proxy) throws Throwable;

    protected abstract Object remove(Class interfce, Method method, Object[] args, Object proxy) throws Throwable;

    protected Object businessMethod(final Class<?> interfce, final Method method, final Object[] args, final Object proxy) throws Throwable {
        final BeanContext beanContext = getBeanContext();

        if (beanContext.isAsynchronous(method)) {

            final SecurityService securityService = SystemInstance.get().getComponent(SecurityService.class);

            if(null == securityService){
                throw new RuntimeException("SecurityService has not been initialized");
            }

            Object stateTmp = securityService.currentState();
            final boolean associate;
            if (stateTmp == null) {
                stateTmp = ClientSecurity.getIdentity();
                associate = stateTmp != null;
            } else {
                associate = false;
            }
            final Object securityState = stateTmp;

            final ThreadContext threadContext = ThreadContext.getThreadContext();
            final AsynchronousPool asynchronousPool = beanContext.getModuleContext().getAppContext().getAsynchronousPool();

            return asynchronousPool.invoke(new Callable<Object>() {
                @Override
                public Object call() throws Exception {
                    final Object threadState;
                    if (associate) {
                        //noinspection unchecked
                        securityService.associate(securityState);
                        threadState = null;
                    } else {
                        threadState = securityService.currentState();
                        securityService.setState(securityState);
                    }

                    final ThreadContext oldCtx; // ensure context is the same as for the caller
                    if (threadContext != null) {
                        oldCtx = ThreadContext.enter(new ThreadContext(threadContext));
                    } else {
                        oldCtx = null;
                    }

                    try {
                        return synchronizedBusinessMethod(interfce, method, args);
                    } catch (final ApplicationException ae) {

                        logger.error("EjbObjectProxyHandler: Asynchronous call to '" + interfce.getSimpleName() + "' on '" + method.getName() + "' failed", ae);

                        throw ae;
                    } finally {
                        if (threadContext != null) {
                            ThreadContext.exit(oldCtx);
                        }
                        if (!associate) {
                            securityService.setState(threadState);
                        } else {
                            securityService.disassociate();
                        }
                    }
                }
            }, method.getReturnType() == Void.TYPE);
        } else {
            return synchronizedBusinessMethod(interfce, method, args);
        }
    }

    protected Object synchronizedBusinessMethod(final Class<?> interfce, final Method method, final Object[] args) throws OpenEJBException {
        return container.invoke(deploymentID, interfaceType, interfce, method, args, primaryKey);
    }

    public static Object createProxy(final BeanContext beanContext, final Object primaryKey, final InterfaceType interfaceType, final Class mainInterface) {
        return createProxy(beanContext, primaryKey, interfaceType, null, mainInterface);
    }

    public static Object createProxy(final BeanContext beanContext, final Object primaryKey, InterfaceType interfaceType, final List<Class> interfaces, final Class mainInterface) {
        if (!interfaceType.isHome()) {
            interfaceType = interfaceType.getCounterpart();
        }
        final EjbHomeProxyHandler homeHandler = EjbHomeProxyHandler.createHomeHandler(beanContext, interfaceType, interfaces, mainInterface);
        return homeHandler.createProxy(primaryKey, mainInterface);
    }

}
