/*
 * 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.myfaces.extensions.scripting.jsf.dynamicdecorators.implemetations;

import org.apache.myfaces.el.unified.resolver.FacesCompositeELResolver;
import org.apache.myfaces.extensions.scripting.api.Decorated;
import org.apache.myfaces.extensions.scripting.api.ScriptingConst;
import org.apache.myfaces.extensions.scripting.core.util.WeavingContext;
import org.apache.myfaces.extensions.scripting.jsf2.annotation.purged.*;

import javax.el.*;
import javax.faces.FacesException;
import javax.faces.application.*;
import javax.faces.component.UIComponent;
import javax.faces.component.behavior.Behavior;
import javax.faces.context.FacesContext;
import javax.faces.convert.Converter;
import javax.faces.el.*;
import javax.faces.event.*;
import javax.faces.validator.Validator;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @author Werner Punz
 *         <p/>
 *         our decorating applicstion
 *         which should resolve our bean issues within a central
 *         bean processing interceptor
 */
public class ApplicationProxy extends Application implements Decorated {

    Application _delegate = null;

    /*
    * separate map needed for the behavior ids, because
    * the original is immutable
    * we have to do a double bookkeeping
    * here
    */
    Map<String, String> _behaviors = new ConcurrentHashMap<String, String>();

    /**
     * special data structure to save our
     * object -> proxy references
     */
    class EventHandlerProxyEntry {
        Class event;
        Decorated proxy;

        EventHandlerProxyEntry(Class event, Decorated proxy) {
            this.event = event;
            this.proxy = proxy;
        }

        @SuppressWarnings("unused")
        public Class getEvent() {
            return event;
        }

        @SuppressWarnings("unused")
        public void setEvent(Class event) {
            this.event = event;
        }

        public Decorated getProxy() {
            return proxy;
        }

        @SuppressWarnings("unused")
        public void setProxy(Decorated proxy) {
            this.proxy = proxy;
        }

        @Override
        public boolean equals(Object o) {
            if (this == o) return true;
            if (o == null || getClass() != o.getClass()) return false;

            EventHandlerProxyEntry that = (EventHandlerProxyEntry) o;

            return !(event != null ? !event.equals(that.event) : that.event != null) && !(proxy != null ? !proxy.getDelegate().getClass().getName().equals(that.proxy.getDelegate().getClass().getName()) : that.proxy != null);

        }

        @Override
        public int hashCode() {
            int result = event.hashCode();
            result = 31 * result + proxy.getDelegate().getClass().getName().hashCode();
            return result;
        }
    }

    /**
     * now at the first look this looks like a weird construct
     * but the standard java set imposes this limit since
     * we have to iterate over the entire set to reach the correct element
     * the trick is to save the same object in as both key and value
     * and now if we generate a new key on an object
     * we can fetch our proxy which might already contain
     * the same object in a refreshed state from the value
     * part of the set, in our case
     * using hash maps should speed things up
     * <p/>
     * since we only have few write operations but access
     * the map multithreaded we use concurrentHashMap here
     */
    Map<EventHandlerProxyEntry, EventHandlerProxyEntry> _eventHandlerIdx = new ConcurrentHashMap<EventHandlerProxyEntry, EventHandlerProxyEntry>();

    volatile static boolean varResolverAdded = false;

    ELResolverProxy finalResolver = null;

    public ApplicationProxy(Application delegate) {
        _delegate = delegate;
    }

    public void addELResolver(ELResolver elResolver) {
        weaveDelegate();
        //we do not need a proxy here anymore because
        //we drop the beans directly
        _delegate.addELResolver(elResolver);
    }

    private void weaveDelegate() {
        if (_delegate != null) {
            _delegate = (Application) WeavingContext.getWeaver().reloadScriptingInstance(_delegate, ScriptingConst.ARTIFACT_TYPE_APPLICATION);
        }
    }

    public ELResolver getELResolver() {
        weaveDelegate();

        ELResolver retVal = _delegate.getELResolver();
        return retVal;
    }

    //TOD add a weaving for resource bundles

    public ResourceBundle getResourceBundle(FacesContext facesContext, String s) throws FacesException, NullPointerException {
        weaveDelegate();
        return _delegate.getResourceBundle(facesContext, s);
    }

    public UIComponent createComponent(ValueExpression valueExpression, FacesContext facesContext, String componentType) throws FacesException, NullPointerException {
        weaveDelegate();
        UIComponent component = _delegate.createComponent(valueExpression, facesContext, componentType);
        UIComponent oldComponent = component;
        //We can replace annotated components on the fly via
        //ApplicationImpl.addComponent(final String componentType, final String componentClassName)

        /*we are reweaving on the fly because we cannot be sure if
        * the class is not recycled all the time in the creation
        * code, in the renderer we do it on method base
        * due to the fact that our renderers are recycled via
        * a flyweight pattern
        *
        *
        * Also we cannot proxy here because there is no UIComponent interface
        * maybe in the long run we can make a decorator here instead
        * but for now lets try it this way
        */
        component = (UIComponent) reloadInstance(component, ScriptingConst.ARTIFACT_TYPE_COMPONENT);

        //we now have to check for an annotation change, but only in case a reload has happened
        if (component.getClass().hashCode() != oldComponent.getClass().hashCode()) {
            return handleAnnotationChange(component, valueExpression, facesContext, componentType);
        }

        return component;

    }

    public ExpressionFactory getExpressionFactory() {
        weaveDelegate();
        return _delegate.getExpressionFactory();
    }

    public void addELContextListener(ELContextListener elContextListener) {
        weaveDelegate();
        if (WeavingContext.isDynamic(elContextListener.getClass()))
            elContextListener = (ELContextListener) WeavingContext.createMethodReloadingProxyFromObject(elContextListener, ELContextListener.class, ScriptingConst.ARTIFACT_TYPE_ELCONTEXTLISTENER);
        _delegate.addELContextListener(elContextListener);
    }

    public void removeELContextListener(ELContextListener elContextListener) {
        weaveDelegate();
        _delegate.removeELContextListener(elContextListener);
    }

    public ELContextListener[] getELContextListeners() {
        weaveDelegate();
        return _delegate.getELContextListeners();
    }

    public ActionListener getActionListener() {
        weaveDelegate();
        ActionListener retVal = _delegate.getActionListener();
        if (WeavingContext.isDynamic(retVal.getClass()))
            retVal = (ActionListener) WeavingContext.createMethodReloadingProxyFromObject(retVal, ActionListener.class, ScriptingConst.ARTIFACT_TYPE_ACTIONLISTENER);
        return retVal;
    }

    public void setActionListener(ActionListener actionListener) {
        weaveDelegate();
        if (WeavingContext.isDynamic(actionListener.getClass()))
            actionListener = (ActionListener) WeavingContext.createMethodReloadingProxyFromObject(actionListener, ActionListener.class, ScriptingConst.ARTIFACT_TYPE_ACTIONLISTENER);
        _delegate.setActionListener(actionListener);
    }

    public Locale getDefaultLocale() {
        weaveDelegate();
        return _delegate.getDefaultLocale();
    }

    public void setDefaultLocale(Locale locale) {
        weaveDelegate();
        _delegate.setDefaultLocale(locale);
    }

    public String getDefaultRenderKitId() {
        weaveDelegate();
        return _delegate.getDefaultRenderKitId();
    }

    public void setDefaultRenderKitId(String s) {
        weaveDelegate();
        _delegate.setDefaultRenderKitId(s);
    }

    public String getMessageBundle() {
        weaveDelegate();
        return _delegate.getMessageBundle();
    }

    public void setMessageBundle(String s) {
        weaveDelegate();
        _delegate.setMessageBundle(s);
    }

    public NavigationHandler getNavigationHandler() {
        weaveDelegate();
        //defined in the setter to speed things up a little
        NavigationHandler retVal = _delegate.getNavigationHandler();

        //if (retVal != null && WeavingContext.isDynamic(retVal.getClass()))
        //    retVal = new NavigationHandlerProxy(retVal);
        return retVal;
    }

    public void setNavigationHandler(NavigationHandler navigationHandler) {
        weaveDelegate();

        if (navigationHandler != null && WeavingContext.isDynamic(navigationHandler.getClass()))
            navigationHandler = new NavigationHandlerProxy(navigationHandler);
        _delegate.setNavigationHandler(navigationHandler);
    }

    @SuppressWarnings("deprecation")
    public PropertyResolver getPropertyResolver() {
        weaveDelegate();
        return _delegate.getPropertyResolver();
    }

    @SuppressWarnings("deprecation")
    public void setPropertyResolver(PropertyResolver propertyResolver) {
        weaveDelegate();
        _delegate.setPropertyResolver(propertyResolver);
    }

    @SuppressWarnings("deprecation")
    public VariableResolver getVariableResolver() {
        weaveDelegate();
        return _delegate.getVariableResolver();
    }

    @SuppressWarnings("deprecation")
    public void setVariableResolver(VariableResolver variableResolver) {
        weaveDelegate();
        if(!varResolverAdded) {
            variableResolver = new VariableResolverProxy(variableResolver);
            varResolverAdded = true;
        }
        _delegate.setVariableResolver(variableResolver);
    }

    public ViewHandler getViewHandler() {
        weaveDelegate();
        ViewHandler handler = _delegate.getViewHandler();

        /*
        We proxy here to enable dynamic reloading for
        methods in the long run, as soon as we hit
        java all our groovy reloading code is lost
        hence we have to work with proxies here
        */
        if (WeavingContext.isDynamic(handler.getClass()))
            handler = new ViewHandlerProxy(handler);
        return handler;
    }

    public void setViewHandler(ViewHandler viewHandler) {
        weaveDelegate();
        /*make sure you have the delegates as well in properties*/
        if (WeavingContext.isDynamic(viewHandler.getClass()))
            viewHandler = new ViewHandlerProxy(viewHandler);

        _delegate.setViewHandler(viewHandler);
    }

    public StateManager getStateManager() {
        weaveDelegate();
        return _delegate.getStateManager();
    }

    public void setStateManager(StateManager stateManager) {
        weaveDelegate();
        _delegate.setStateManager(stateManager);
    }

    public void addComponent(String componentType, String componentClass) {
        weaveDelegate();
        _delegate.addComponent(componentType, componentClass);
    }

    public UIComponent createComponent(String componentType) throws FacesException {
        weaveDelegate();
        //the components are generated anew very often
        //we cannot do an on object weaving here
        UIComponent oldComponent = _delegate.createComponent(componentType);

        /*we are reweaving on the fly because we cannot be sure if
        * the class is not recycled all the time in the creation
        * code, in the renderer we do it on method base
        * due to the fact that our renderers are recycled via
        * a flyweight pattern*/
        UIComponent component = (UIComponent) reloadInstance(oldComponent, ScriptingConst.ARTIFACT_TYPE_COMPONENT);

        //we now have to check for an annotation change, but only in case a reload has happened
        if (component.getClass().hashCode() != oldComponent.getClass().hashCode()) {
            return handleAnnotationChange(component, componentType);
        }

        return component;

    }

    @SuppressWarnings("deprecation")
    public UIComponent createComponent(ValueBinding valueBinding, FacesContext facesContext, String componentType) throws FacesException {
        weaveDelegate();
        UIComponent oldComponent = _delegate.createComponent(valueBinding, facesContext, componentType);

        /*we are reweaving on the fly because we cannot be sure if
         * the class is not recycled all the time in the creation
         * code, in the renderer we do it on method base
         * due to the fact that our renderers are recycled via
         * a flyweight pattern*/
        UIComponent component = (UIComponent) reloadInstance(oldComponent, ScriptingConst.ARTIFACT_TYPE_COMPONENT);

        //we now have to check for an annotation change, but only in case a reload has happened
        if (component.getClass().hashCode() != oldComponent.getClass().hashCode()) {
            return handleAnnotationChange(component, valueBinding, facesContext, componentType);
        }

        return component;
    }

    public Iterator<String> getComponentTypes() {
        weaveDelegate();
        return _delegate.getComponentTypes();
    }

    public void addConverter(String converterId, String converterClass) {
        weaveDelegate();
        /* if (converterClass.equals(PurgedConverter.class.getName())) {
            //purged case we do a full rescan
            WeavingContext.getWeaver().fullClassScan();
            Converter componentToChange = _delegate.createConverter(converterId);
            if (componentToChange instanceof PurgedConverter) {
                //Null not allowed here, but we set a purted converter to make
                //sure that we get errors on the proper level
                _delegate.addConverter(converterId, PurgedConverter.class.getName());
            }
            return;
        }*/

        _delegate.addConverter(converterId, converterClass);
    }

    public void addConverter(Class targetClass, String converterClass) {
        weaveDelegate();
        _delegate.addConverter(targetClass, converterClass);
    }

    public Converter createConverter(String converterId) {
        weaveDelegate();
        Converter retVal = _delegate.createConverter(converterId);

        /**
         * since createConverter is called only once
         * we have to work with method reloading proxies
         * we cannot use this technique extensively for speed reasons
         * most of the time it is fine just to work with
         *
         * reloading objects at their interception points
         */
        Converter newRetVal = (Converter) reloadInstance(retVal, ScriptingConst.ARTIFACT_TYPE_CONVERTER);
        if (newRetVal != retVal) {
            return _delegate.createConverter(converterId);
        }

        return retVal;
    }

    public Converter createConverter(Class aClass) {
        weaveDelegate();
        Converter retVal = _delegate.createConverter(aClass);
        Converter newRetVal = (Converter) reloadInstance(retVal, ScriptingConst.ARTIFACT_TYPE_CONVERTER);
        if (newRetVal != retVal) {
            return _delegate.createConverter(aClass);
        }

        return retVal;
    }

    public Iterator<String> getConverterIds() {
        weaveDelegate();
        return _delegate.getConverterIds();
    }

    public Iterator<Class<?>> getConverterTypes() {
        weaveDelegate();
        return _delegate.getConverterTypes();
    }

    @SuppressWarnings("deprecation")
    public MethodBinding createMethodBinding(String s, Class[] classes) throws ReferenceSyntaxException {
        weaveDelegate();
        return _delegate.createMethodBinding(s, classes);
    }

    public Iterator<Locale> getSupportedLocales() {
        weaveDelegate();
        return _delegate.getSupportedLocales();
    }

    public void setSupportedLocales(Collection<Locale> locales) {
        weaveDelegate();
        _delegate.setSupportedLocales(locales);
    }

    public void addValidator(String validatorId, String validatorClass) {
        weaveDelegate();
/*        if (validatorClass.equals(PurgedValidator.class.getName())) {
            //purged case we do a full rescane
            WeavingContext.getWeaver().fullClassScan();
            Validator componentToChange = _delegate.createValidator(validatorId);
            if (componentToChange instanceof PurgedValidator) {
                //Null not allowed here, but we set a purted validator to make
                //sure that we get errors on the proper level
                _delegate.addValidator(validatorId, PurgedValidator.class.getName());

            }
            return;
        } */
        _delegate.addValidator(validatorId, validatorClass);
    }

    public Validator createValidator(String validatorId) throws FacesException {
        weaveDelegate();

        Validator retVal = _delegate.createValidator(validatorId);

        //the validators are recreated every request we do not have to deal with them on method level
        Validator newRetVal = (Validator) reloadInstance(retVal, ScriptingConst.ARTIFACT_TYPE_VALIDATOR);
        if (newRetVal != retVal) {
            _delegate.createValidator(validatorId);
        }
        return retVal;
    }

    public Iterator<String> getValidatorIds() {
        weaveDelegate();
        return _delegate.getValidatorIds();
    }

    @SuppressWarnings("deprecation")
    public ValueBinding createValueBinding(String s) throws ReferenceSyntaxException {
        weaveDelegate();
        return _delegate.createValueBinding(s);
    }

    @Override
    public void addBehavior(String behaviorId, String behaviorClass) {
        weaveDelegate();

        if (behaviorClass.equals(PurgedValidator.class.getName())) {
            //purged case we do a full rescan
            WeavingContext.getWeaver().fullClassScan();
            Behavior behavior = _delegate.createBehavior(behaviorId);
            _behaviors.put(behaviorId, behaviorClass);
            if (behavior instanceof PurgedBehavior) {
                //Null not allowed here, but we set a purged validator to make
                //sure that we get errors on the proper level
                _delegate.addBehavior(behaviorId, PurgedBehavior.class.getName());
                _behaviors.remove(behaviorId);

            }
            return;
        }

        _delegate.addBehavior(behaviorId, behaviorClass);
    }

    @Override
    public void addDefaultValidatorId(String validatorId) {
        weaveDelegate();
        _delegate.addDefaultValidatorId(validatorId);
    }

    @Override
    public Behavior createBehavior(String behaviorId) throws FacesException {
        weaveDelegate();
        Behavior retVal = _delegate.createBehavior(behaviorId);

        //we might have casts here against one of the parents
        //of this object
        Behavior newBehavior = (Behavior) reloadInstance(retVal, ScriptingConst.ARTIFACT_TYPE_BEHAVIOR);
        if (newBehavior != retVal) {
            return _delegate.createBehavior(behaviorId);
        }

        return retVal;
    }

    @Override
    public UIComponent createComponent(FacesContext facesContext, Resource resource) {
        weaveDelegate();

        UIComponent oldComponent = _delegate.createComponent(facesContext, resource);

        /*we are reweaving on the fly because we cannot be sure if
         * the class is not recycled all the time in the creation
         * code, in the renderer we do it on method base
         * due to the fact that our renderers are recycled via
         * a flyweight pattern*/
        UIComponent component = (UIComponent) reloadInstance(oldComponent, ScriptingConst.ARTIFACT_TYPE_COMPONENT);

        //we now have to check for an annotation change, but only in case a reload has happened
        if (component.getClass().hashCode() != oldComponent.getClass().hashCode()) {
            return handleAnnotationChange(component, facesContext, resource);
        }

        return component;

    }

    @Override
    public UIComponent createComponent(FacesContext facesContext, String componentType, String rendererType) {
        weaveDelegate();
        UIComponent oldComponent = _delegate.createComponent(facesContext, componentType, rendererType);

        /*we are reweaving on the fly because we cannot be sure if
         * the class is not recycled all the time in the creation
         * code, in the renderer we do it on method base
         * due to the fact that our renderers are recycled via
         * a flyweight pattern*/
        UIComponent component = (UIComponent) reloadInstance(oldComponent, ScriptingConst.ARTIFACT_TYPE_COMPONENT);

        //we now have to check for an annotation change, but only in case a reload has happened
        if (component.getClass().hashCode() != oldComponent.getClass().hashCode()) {
            return handleAnnotationChange(component, facesContext, componentType, rendererType);
        }

        return component;
    }

    @Override
    public UIComponent createComponent(ValueExpression valueExpression, FacesContext facesContext, String s, String s1) {
        weaveDelegate();
        UIComponent oldComponent = _delegate.createComponent(valueExpression, facesContext, s, s1);

        /*we are reweaving on the fly because we cannot be sure if
     * the class is not recycled all the time in the creation
     * code, in the renderer we do it on method base
     * due to the fact that our renderers are recycled via
     * a flyweight pattern*/
        UIComponent component = (UIComponent) reloadInstance(oldComponent, ScriptingConst.ARTIFACT_TYPE_COMPONENT);

        //we now have to check for an annotation change, but only in case a reload has happened
        if (component.getClass().hashCode() != oldComponent.getClass().hashCode()) {
            return handleAnnotationChange(component, valueExpression, facesContext, s, s1);
        }

        return component;
    }

    @Override
    @SuppressWarnings("unchecked")
    public <T> T evaluateExpressionGet(FacesContext facesContext, String s, Class<? extends T> aClass) throws ELException {
        weaveDelegate();
        //good place for a dynamic reloading check as well
        T retVal = _delegate.evaluateExpressionGet(facesContext, s, aClass);
        if (WeavingContext.isDynamic(retVal.getClass()))
            retVal = (T) WeavingContext.getWeaver().reloadScriptingInstance(retVal, ScriptingConst.ARTIFACT_TYPE_MANAGEDBEAN);
        return retVal;
    }

    @Override
    public Iterator<String> getBehaviorIds() {
        weaveDelegate();
        return _behaviors.keySet().iterator();
        //return _delegate.getBehaviorIds();
    }

    @Override
    public Map<String, String> getDefaultValidatorInfo() {
        weaveDelegate();
        return _delegate.getDefaultValidatorInfo();
    }

    @Override
    public ProjectStage getProjectStage() {
        weaveDelegate();
        return _delegate.getProjectStage();
    }

    @Override
    public ResourceHandler getResourceHandler() {
        weaveDelegate();
        ResourceHandler retVal = _delegate.getResourceHandler();

        /*if (WeavingContext.isDynamic(retVal.getClass())) {
           ResourceHandler newHandler = (ResourceHandler) reloadInstance(retVal, ScriptingConst.ARTIFACT_TYPE_RESOURCEHANDLER);
           if (newHandler != retVal) {
               _delegate.setResourceHandler(newHandler);
               return newHandler;
           }
       } */
        return retVal;
    }

    @Override
    public void publishEvent(FacesContext facesContext, Class<? extends SystemEvent> eventClass, Class<?> sourceBaseTye, Object source) {
        weaveDelegate();
        _delegate.publishEvent(facesContext, eventClass, sourceBaseTye, source);
    }

    @Override
    public void publishEvent(FacesContext facesContext, Class<? extends SystemEvent> eventClass, Object source) {
        weaveDelegate();
        _delegate.publishEvent(facesContext, eventClass, source);
    }

    @Override
    public void setResourceHandler(ResourceHandler resourceHandler) {
        weaveDelegate();
        if (WeavingContext.isDynamic(resourceHandler.getClass())) {
            ResourceHandler proxy = new ResourceHandlerProxy(resourceHandler);
            resourceHandler = proxy;
        }

        _delegate.setResourceHandler(resourceHandler);
        //ResourceHandler handler = _delegate.getResourceHandler();
        //if (handler instanceof PurgedResourceHandler) {
        //    WeavingContext.getWeaver().fullClassScan();
        //}
    }

    @Override
    public void subscribeToEvent(Class<? extends SystemEvent> eventClass, Class<?> aClass, SystemEventListener systemEventListener) {
        weaveDelegate();
        systemEventListener = makeEventProxy(eventClass, systemEventListener);
        _delegate.subscribeToEvent(eventClass, aClass, systemEventListener);
    }

    private SystemEventListener makeEventProxy(Class<? extends SystemEvent> eventClass, SystemEventListener systemEventListener) {
        if (WeavingContext.isDynamic(systemEventListener.getClass())) {
            systemEventListener = new SystemEventListenerProxy(systemEventListener);
            EventHandlerProxyEntry entry = new EventHandlerProxyEntry(eventClass, (Decorated) systemEventListener);
            _eventHandlerIdx.put(entry, entry);
        }
        return systemEventListener;
    }

    @Override
    public void subscribeToEvent(Class<? extends SystemEvent> eventClass, SystemEventListener systemEventListener) {
        weaveDelegate();
        systemEventListener = makeEventProxy(eventClass, systemEventListener);
        _delegate.subscribeToEvent(eventClass, systemEventListener);
    }

    @Override
    public void unsubscribeFromEvent(Class<? extends SystemEvent> eventClass, Class<?> aClass, SystemEventListener systemEventListener) {
        weaveDelegate();
        systemEventListener = resolveEventProxy(eventClass, systemEventListener);
        _delegate.unsubscribeFromEvent(eventClass, aClass, systemEventListener);
    }

    private SystemEventListener resolveEventProxy(Class<? extends SystemEvent> eventClass, SystemEventListener systemEventListener) {
        if (WeavingContext.isDynamic(systemEventListener.getClass())) {
            systemEventListener = new SystemEventListenerProxy(systemEventListener);
            EventHandlerProxyEntry entry = new EventHandlerProxyEntry(eventClass, (Decorated) systemEventListener);
            entry = _eventHandlerIdx.remove(entry);
            if (entry != null) {
                systemEventListener = (SystemEventListener) entry.getProxy().getDelegate();
            }
        }
        return systemEventListener;
    }

    @Override
    public void unsubscribeFromEvent(Class<? extends SystemEvent> eventClass, SystemEventListener systemEventListener) {
        weaveDelegate();
        systemEventListener = resolveEventProxy(eventClass, systemEventListener);
        _delegate.unsubscribeFromEvent(eventClass, systemEventListener);
    }

    public Object getDelegate() {
        return _delegate;
    }

    private Object reloadInstance(Object instance, int artifactType) {
        if (instance == null) {
            return null;
        }
        if (WeavingContext.isDynamic(instance.getClass()) && !alreadyWovenInRequest(instance.getClass().getName())) {
            instance = WeavingContext.getWeaver().reloadScriptingInstance(instance, artifactType);
            alreadyWovenInRequest(instance.getClass().getName());
        }
        return instance;
    }

    private boolean alreadyWovenInRequest(String clazz) {
        //portlets now can be enabled thanks to the jsf2 indirections regarding the external context
        Map<String, Object> req = WeavingContext.getRequestMap();
        if (req.get(ScriptingConst.SCRIPTING_REQUSINGLETON + clazz) == null) {
            req.put(ScriptingConst.SCRIPTING_REQUSINGLETON + clazz, "");
            return false;
        }
        return true;
    }

    private UIComponent handleAnnotationChange(UIComponent oldComponent, ValueExpression valueExpression, FacesContext facesContext, String componentType) {
        UIComponent componentToChange = _delegate.createComponent(valueExpression, facesContext, componentType);
        if (componentToChange instanceof PurgedComponent) {
            WeavingContext.getWeaver().fullClassScan();
            //via an additional create component we can check whether a purged component
            //was registered after the reload because the annotation has been removed
            componentToChange = _delegate.createComponent(valueExpression, facesContext, componentType);

            return componentToChange;
        }
        return oldComponent;
    }

    private UIComponent handleAnnotationChange(UIComponent oldComponent, String componentType) {
        UIComponent componentToChange = _delegate.createComponent(componentType);
        if (componentToChange instanceof PurgedComponent) {
            WeavingContext.getWeaver().fullClassScan();
            //via an additional create component we can check whether a purged component
            //was registered after the reload because the annotation has been removed
            componentToChange = _delegate.createComponent(componentType);

            return componentToChange;
        }
        return oldComponent;
    }

    @SuppressWarnings("deprecation")
    private UIComponent handleAnnotationChange(UIComponent oldComponent, ValueBinding valueBinding, FacesContext context, String componentType) {
        UIComponent componentToChange = _delegate.createComponent(valueBinding, context, componentType);
        if (componentToChange instanceof PurgedComponent) {
            WeavingContext.getWeaver().fullClassScan();
            //via an additional create component we can check whether a purged component
            //was registered after the reload because the annotation has been removed
            componentToChange = _delegate.createComponent(valueBinding, context, componentType);

            return componentToChange;
        }
        return oldComponent;
    }

    private UIComponent handleAnnotationChange(UIComponent oldComponent, FacesContext context, Resource resource) {
        UIComponent componentToChange = _delegate.createComponent(context, resource);
        if (componentToChange instanceof PurgedComponent) {
            WeavingContext.getWeaver().fullClassScan();
            //via an additional create component we can check whether a purged component
            //was registered after the reload because the annotation has been removed
            componentToChange = _delegate.createComponent(context, resource);

            return componentToChange;
        }
        return oldComponent;
    }

    private UIComponent handleAnnotationChange(UIComponent oldComponent, FacesContext context, String componentType, String rendererType) {
        UIComponent componentToChange = _delegate.createComponent(context, componentType, rendererType);
        if (componentToChange instanceof PurgedComponent) {
            WeavingContext.getWeaver().fullClassScan();
            //via an additional create component we can check whether a purged component
            //was registered after the reload because the annotation has been removed
            componentToChange = _delegate.createComponent(context, componentType, rendererType);

            return componentToChange;
        }
        return oldComponent;
    }

    private UIComponent handleAnnotationChange(UIComponent oldComponent, ValueExpression valueExpression, FacesContext facesContext, String s, String s1) {
        UIComponent componentToChange = _delegate.createComponent(valueExpression, facesContext, s, s1);
        if (componentToChange instanceof PurgedComponent) {
            WeavingContext.getWeaver().fullClassScan();

            //via an additional create component we can check whether a purged component
            //was registered after the reload because the annotation has been removed

            componentToChange = _delegate.createComponent(valueExpression, facesContext, s, s1);

            return componentToChange;
        }
        return oldComponent;
    }

}
