/*
 * 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.tuscany.sca.core.context.impl;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

import org.apache.tuscany.sca.assembly.AssemblyFactory;
import org.apache.tuscany.sca.assembly.Binding;
import org.apache.tuscany.sca.assembly.Component;
import org.apache.tuscany.sca.assembly.ComponentProperty;
import org.apache.tuscany.sca.assembly.ComponentReference;
import org.apache.tuscany.sca.assembly.ComponentService;
import org.apache.tuscany.sca.assembly.CompositeService;
import org.apache.tuscany.sca.assembly.Endpoint;
import org.apache.tuscany.sca.assembly.EndpointReference;
import org.apache.tuscany.sca.assembly.Multiplicity;
import org.apache.tuscany.sca.assembly.SCABinding;
import org.apache.tuscany.sca.assembly.Service;
import org.apache.tuscany.sca.context.CompositeContext;
import org.apache.tuscany.sca.context.ContextFactoryExtensionPoint;
import org.apache.tuscany.sca.context.PropertyValueFactory;
import org.apache.tuscany.sca.context.RequestContextFactory;
import org.apache.tuscany.sca.core.ExtensionPointRegistry;
import org.apache.tuscany.sca.core.FactoryExtensionPoint;
import org.apache.tuscany.sca.core.UtilityExtensionPoint;
import org.apache.tuscany.sca.core.invocation.ExtensibleProxyFactory;
import org.apache.tuscany.sca.core.invocation.ProxyFactory;
import org.apache.tuscany.sca.interfacedef.Interface;
import org.apache.tuscany.sca.interfacedef.InterfaceContract;
import org.apache.tuscany.sca.interfacedef.InvalidInterfaceException;
import org.apache.tuscany.sca.interfacedef.java.JavaInterface;
import org.apache.tuscany.sca.interfacedef.java.JavaInterfaceContract;
import org.apache.tuscany.sca.interfacedef.java.JavaInterfaceFactory;
import org.apache.tuscany.sca.runtime.CompositeActivator;
import org.apache.tuscany.sca.runtime.EndpointReferenceBinder;
import org.apache.tuscany.sca.runtime.RuntimeComponent;
import org.apache.tuscany.sca.runtime.RuntimeComponentContext;
import org.apache.tuscany.sca.runtime.RuntimeComponentReference;
import org.apache.tuscany.sca.runtime.RuntimeEndpoint;
import org.apache.tuscany.sca.runtime.RuntimeEndpointReference;
import org.oasisopen.sca.RequestContext;
import org.oasisopen.sca.ServiceReference;
import org.oasisopen.sca.ServiceRuntimeException;

import org.apache.tuscany.sca.interfacedef.InterfaceContractMapper;

/**
 * Implementation of ComponentContext that delegates to a ComponentContextProvider.
 *
 * @version $Rev$ $Date$
 */
public class ComponentContextImpl implements RuntimeComponentContext {
    private final RuntimeComponent component;

    private final CompositeContext compositeContext;
    private final CompositeActivator compositeActivator;
    private final RequestContextFactory requestContextFactory;
    private final ProxyFactory proxyFactory;
    private final AssemblyFactory assemblyFactory;
    private final JavaInterfaceFactory javaInterfaceFactory;
    private final PropertyValueFactory propertyFactory;
    private final EndpointReferenceBinder eprBinder;
    private final ExtensionPointRegistry registry;

    public ComponentContextImpl(ExtensionPointRegistry registry,
                                CompositeContext compositeContext,
                                RuntimeComponent component) {
        this.component = component;
        FactoryExtensionPoint factories = registry.getExtensionPoint(FactoryExtensionPoint.class);
        this.assemblyFactory = factories.getFactory(AssemblyFactory.class);
        this.javaInterfaceFactory = factories.getFactory(JavaInterfaceFactory.class);

        UtilityExtensionPoint utilities = registry.getExtensionPoint(UtilityExtensionPoint.class);
        this.compositeContext = compositeContext;

        this.compositeActivator = utilities.getUtility(CompositeActivator.class);

        this.requestContextFactory =
            registry.getExtensionPoint(ContextFactoryExtensionPoint.class).getFactory(RequestContextFactory.class);
        this.proxyFactory = ExtensibleProxyFactory.getInstance(registry);
        this.propertyFactory = factories.getFactory(PropertyValueFactory.class);

        this.eprBinder = utilities.getUtility(EndpointReferenceBinder.class);

        this.registry = registry;
    }

    public String getURI() {
        return component.getURI();
    }

    public <B> ServiceReference<B> cast(B target) throws IllegalArgumentException {
        return proxyFactory.cast(target);
    }

    public <B> B getService(Class<B> businessInterface, String referenceName) throws IllegalArgumentException {
    	B service = null;
    	
     	ServiceReference<B> serviceRef = getServiceReference(businessInterface, referenceName);
     	if(serviceRef != null) {
            service = serviceRef.getService();
     	}

        return service;
    }

    public <B> ServiceReference<B> getServiceReference(Class<B> businessInterface, String referenceName) throws IllegalArgumentException {

        for (ComponentReference ref : component.getReferences()) {
            if (referenceName.equals(ref.getName())) {
                Multiplicity multiplicity = ref.getMultiplicity();
                if (multiplicity == Multiplicity.ZERO_N || multiplicity == Multiplicity.ONE_N) {
                    throw new IllegalArgumentException("Reference " + referenceName
                        + " has multiplicity "
                        + multiplicity);
                }
                if (ref.getEndpointReferences().size() < 1) {
                    return null;
                }
                ServiceReference<B> sr = getServiceReference(businessInterface, (RuntimeEndpointReference)getEndpointReference(ref));
                if (sr == null) {
                    throw new IllegalArgumentException("Reference " + referenceName + " is null");
                }
                return sr;
            }
        }
        throw new IllegalArgumentException("[JCA80011] Reference not found: " + referenceName);

    }

    /**
     * Select an endpoint reference from the component reference
     * @param ref
     * @return
     */
    private EndpointReference getEndpointReference(ComponentReference ref) {
        List<EndpointReference> eprs = ref.getEndpointReferences();
        if (eprs.size() == 1) {
            // Return 1st one
            return eprs.get(0);
        } else {
            for (EndpointReference epr : eprs) {
                // Try to see if there is an EPR using binding.sca
                if (epr.getBinding().getType().equals(SCABinding.TYPE)) {
                    return epr;
                }
            }
            return eprs.get(0);
        }
    }

    /**
     * Select an endpoint reference from the component reference
     * @param ref
     * @return
     */
    private Endpoint getEndpoint(ComponentService service, String bindingName) {
        if (bindingName == null) {
            // The default binding name is the name of the promoted service
            bindingName = getPromotedService(service).getName();
        }
        Endpoint returnEp = null;
        List<Endpoint> eps = service.getEndpoints();
        for (Endpoint ep : eps) {
            Binding binding = ep.getBinding();
            if (bindingName.equals(binding.getName()) || binding.getName() == null) {
                returnEp = ep;
                break;
            }
        }
        //TUSCANY-3543
        if(returnEp == null) {
            returnEp = eps.get(0);
        }
        
        return returnEp;
    }

    private ComponentService getPromotedService(ComponentService componentService) {
        Service service = componentService.getService();
        if (service instanceof CompositeService) {
            return getPromotedService(((CompositeService)service).getPromotedService());
        } else {
            return componentService;
        }

    }

    /**
     * Gets the value for the specified property with the specified type.
     * 
     * @param type The type of the property value we are getting
     * @param propertyName The name of the property we are getting
     * @param B The class of the property value we are getting
     * 
     * @throws ServiceRuntimeException If a Property for the specified propertyName
     *         is not found 
     *         
     * @see #setPropertyValueFactory(PropertyValueFactory)         
     */
    public <B> B getProperty(Class<B> type, String propertyName) {
        for (ComponentProperty p : component.getProperties()) {
            if (propertyName.equals(p.getName())) {
            	return propertyFactory.createPropertyValue(p, type);           
            }
        }
        throw new IllegalArgumentException("Property not found: " + propertyName);
    }

    /**
     * @param component
     */
    public static ComponentService getSingleService(Component component) {
        ComponentService targetService;
        List<ComponentService> services = component.getServices();
        List<ComponentService> regularServices = new ArrayList<ComponentService>();
        for (ComponentService service : services) {
            if (service.isForCallback()) {
                continue;
            }
            String name = service.getName();
            if (!name.startsWith("$") || name.startsWith("$dynamic$")) {
                regularServices.add(service);
            }
        }
        if (regularServices.size() == 0) {
            throw new ServiceRuntimeException("No service is declared on component " + component.getURI());
        }
        if (regularServices.size() != 1) {
            throw new ServiceRuntimeException("More than one service is declared on component " + component.getURI()
                + ". Service name is required to get the service.");
        }
        targetService = regularServices.get(0);
        return targetService;
    }

    public <B> ServiceReference<B> createSelfReference(Class<B> businessInterface) {
        ComponentService service = getSingleService(component);
        try {
            return createSelfReference(businessInterface, service);
        } catch (IllegalArgumentException iae) {
        	throw iae;
        } catch (Exception e) {
            throw new ServiceRuntimeException(e.getMessage(), e);
        }
    }

    public <B> ServiceReference<B> createSelfReference(Class<B> businessInterface, String serviceName) {
        if (serviceName == null) {
            return createSelfReference(businessInterface);
        }
        try {
            String bindingName = null;
            int index = serviceName.indexOf('/');
            if (index != -1) {
                bindingName = serviceName.substring(index + 1);
                serviceName = serviceName.substring(0, index);
            }
            for (ComponentService service : component.getServices()) {
                if (serviceName.equals(service.getName())) {
                    Endpoint endpoint = getEndpoint(service, bindingName);
                    if (endpoint == null) {
                        break;
                    }
                    return getServiceReference(businessInterface, (RuntimeEndpoint)endpoint);
                }
            }
            throw new IllegalArgumentException("Service not found: " + serviceName);
        } catch (IllegalArgumentException iae) {
        	throw iae;
        } catch (ServiceRuntimeException e) {
            throw e;
        } catch (Exception e) {
            throw new ServiceRuntimeException(e.getMessage(), e);
        }
    }

    /**
     * @param <B>
     * @param businessInterface
     * @param service
     * @return
     */
    public <B> ServiceReference<B> createSelfReference(Class<B> businessInterface, ComponentService service) {
        try {
            RuntimeEndpointReference ref =
                (RuntimeEndpointReference)createEndpointReference(component, service, null, businessInterface);
            ref.setComponent(component);
            return getServiceReference(businessInterface, ref);
        } catch (IllegalArgumentException iae) {
        	throw iae;
        } catch (Exception e) {
            throw new ServiceRuntimeException(e);
        }
    }

    public RequestContext getRequestContext() {
        if (requestContextFactory != null) {
            return requestContextFactory.createRequestContext(component);
        } else {
            return new RequestContextImpl(component);
        }
    }

    /**
     * @param businessInterface
     * @param reference
     * @return
     * @throws CloneNotSupportedException
     * @throws InvalidInterfaceException
     */
    public <B> ServiceReference<B> getServiceReference(Class<B> businessInterface,
                                                       RuntimeEndpointReference endpointReference) {
    	ServiceReference<B> result = null;
    	
        try {
            InterfaceContract interfaceContract = endpointReference.getComponentTypeReferenceInterfaceContract();
            if (businessInterface == null) {
                businessInterface = (Class<B>)((JavaInterface)interfaceContract.getInterface()).getJavaClass();
            }
            RuntimeComponentReference ref = (RuntimeComponentReference)endpointReference.getReference();
            InterfaceContract refInterfaceContract = getInterfaceContract(interfaceContract, businessInterface);
            if (refInterfaceContract != null) {
	            if (refInterfaceContract != interfaceContract) {
	                ref = (RuntimeComponentReference)ref.clone();
	                if (interfaceContract != null) {
	                    ref.setInterfaceContract(interfaceContract);
	                } else {
	                    ref.setInterfaceContract(refInterfaceContract);
	                }
	            }
 
	            ref.setComponent(component);
	            result = new ServiceReferenceImpl<B>(businessInterface, endpointReference, component.getComponentContext().getCompositeContext());
            }
        } catch (IllegalArgumentException iae ) {
        	throw iae;
        } catch (Exception e) {
            throw new ServiceRuntimeException(e);
        }
        
        return result;
    }

    public <B> ServiceReference<B> getServiceReference(Class<B> businessInterface, RuntimeEndpoint endpoint) {
        try {
            if (businessInterface == null) {
                InterfaceContract contract = endpoint.getComponentTypeServiceInterfaceContract();
                businessInterface = (Class<B>)((JavaInterface)contract.getInterface()).getJavaClass();
            }
            RuntimeEndpointReference ref =
                (RuntimeEndpointReference)createEndpointReference(endpoint, businessInterface);
            ref.setComponent(component);
            return new ServiceReferenceImpl<B>(businessInterface, ref, compositeContext);
        } catch (IllegalArgumentException iae) {
        	throw iae;
        } catch (Exception e) {
            throw new ServiceRuntimeException(e);
        }
    }

    /**
     * Create a self-reference for a component service
     * @param component
     * @param service
     * @throws CloneNotSupportedException 
     * @throws InvalidInterfaceException 
     */
    private EndpointReference createEndpointReference(Component component,
                                                      ComponentService service,
                                                      String bindingName,
                                                      Class<?> businessInterface) throws CloneNotSupportedException,
        InvalidInterfaceException {

        Endpoint endpoint = getEndpoint(service, bindingName);
        return createEndpointReference(endpoint, businessInterface);
    }

    private EndpointReference createEndpointReference(Endpoint endpoint, Class<?> businessInterface)
        throws CloneNotSupportedException, InvalidInterfaceException {
        Component component = endpoint.getComponent();
        ComponentService service = endpoint.getService();
        ComponentReference componentReference = assemblyFactory.createComponentReference();
        componentReference.setName("$self$." + service.getName());

        componentReference.setCallback(service.getCallback());
        componentReference.getTargets().add(service);
        componentReference.getPolicySets().addAll(service.getPolicySets());
        componentReference.getRequiredIntents().addAll(service.getRequiredIntents());
        componentReference.getBindings().add(endpoint.getBinding());

        InterfaceContract interfaceContract = service.getInterfaceContract();
        Service componentTypeService = service.getService();
        if (componentTypeService != null && componentTypeService.getInterfaceContract() != null) {
            interfaceContract = componentTypeService.getInterfaceContract();
        }
        interfaceContract = getInterfaceContract(interfaceContract, businessInterface);
        componentReference.setInterfaceContract(interfaceContract);
        componentReference.setMultiplicity(Multiplicity.ONE_ONE);
        // component.getReferences().add(componentReference);

        // create endpoint reference
        EndpointReference endpointReference = assemblyFactory.createEndpointReference();
        endpointReference.setComponent(component);
        endpointReference.setReference(componentReference);
        endpointReference.setBinding(endpoint.getBinding());
        endpointReference.setUnresolved(false);
        endpointReference.setStatus(EndpointReference.Status.WIRED_TARGET_FOUND_READY_FOR_MATCHING);

        endpointReference.setTargetEndpoint(endpoint);

        componentReference.getEndpointReferences().add(endpointReference);
        ((RuntimeComponentReference)componentReference).setComponent((RuntimeComponent)component);
        ((RuntimeEndpointReference)endpointReference).bind(compositeContext);

        return endpointReference;
    }

    /**
     * @param interfaceContract
     * @param businessInterface
     * @return
     * @throws CloneNotSupportedException
     * @throws InvalidInterfaceException
     */
    private InterfaceContract getInterfaceContract(InterfaceContract interfaceContract, Class<?> businessInterface)
        throws CloneNotSupportedException, InvalidInterfaceException {
        if (businessInterface == null) {
            return interfaceContract;
        }
        if (interfaceContract == null) {
            JavaInterfaceContract ic = javaInterfaceFactory.createJavaInterfaceContract();
            ic.setInterface(javaInterfaceFactory.createJavaInterface(businessInterface));
            return ic;
        }
        boolean compatible = false;
        if (interfaceContract != null && interfaceContract.getInterface() != null) {
            Interface interfaze = interfaceContract.getInterface();
            if (interfaze instanceof JavaInterface) {
                Class<?> cls = ((JavaInterface)interfaze).getJavaClass();
                if (businessInterface.isAssignableFrom(cls)) {
                    compatible = true;
                }
                if(!compatible) {
                    InterfaceContract biContract = javaInterfaceFactory.createJavaInterfaceContract();
                    JavaInterface callInterface = javaInterfaceFactory.createJavaInterface(businessInterface);
                    biContract.setInterface(callInterface);
                    if (callInterface.getCallbackClass() != null) {
                        biContract.setCallbackInterface(javaInterfaceFactory.createJavaInterface(callInterface
                            .getCallbackClass()));
                    }
                	InterfaceContractMapper ifcm = registry.getExtensionPoint(InterfaceContractMapper.class);
                	compatible = ifcm.isCompatibleSubset(biContract , interfaceContract);
                }

            }
        }
        
        if(!compatible) {
        	// JCA-9011
        	throw new IllegalArgumentException("Business interface " + businessInterface.getName() + " is not compatible with " + interfaceContract.getInterface().getClass().getName());
        }

        return interfaceContract;
    }

    /**
     * @see org.apache.tuscany.sca.runtime.RuntimeComponentContext#start(org.apache.tuscany.sca.runtime.RuntimeComponentReference)
     */
    public void start(RuntimeComponentReference reference) {
        compositeActivator.start(compositeContext, component, reference);
    }

    /* ******************** Contribution for issue TUSCANY-2281 ******************** */

    /**
     * @see ComponentContext#getServices(Class<B>, String)
     */
    public <B> Collection<B> getServices(Class<B> businessInterface, String referenceName) {
        ArrayList<B> services = new ArrayList<B>();
        Collection<ServiceReference<B>> serviceRefs = getServiceReferences(businessInterface, referenceName);
        for (ServiceReference<B> serviceRef : serviceRefs) {
            services.add(serviceRef.getService());
        }
        return services;
    }

    /**
     * @see ComponentContext#getServiceReferences(Class<B>, String)
     */
    public <B> Collection<ServiceReference<B>> getServiceReferences(Class<B> businessInterface, String referenceName) {
        try {
            for (ComponentReference ref : component.getReferences()) {
                if (referenceName.equals(ref.getName())) {
                	if ( ref.getMultiplicity() == Multiplicity.ONE_ONE ) 
                		throw new IllegalArgumentException("Reference " + referenceName + " is not a valid argument for getServiceReferences because it has a multiplicity of 1..1");
                	if (ref.getMultiplicity() == Multiplicity.ZERO_ONE)
                		throw new IllegalArgumentException("Reference " + referenceName + " is not a valid argument for getServiceReferences because it has a multiplicity of 0..1");
                		
                    ArrayList<ServiceReference<B>> serviceRefs = new ArrayList<ServiceReference<B>>();
                    for (EndpointReference endpointReference : ref.getEndpointReferences()) {
                        RuntimeEndpointReference epr = (RuntimeEndpointReference)endpointReference;
                        serviceRefs.add(getServiceReference(businessInterface, epr));
                    }
                    return serviceRefs;
                }
            }
            throw new IllegalArgumentException("Reference not found: " + referenceName);
        } catch (IllegalArgumentException iae) {
        	throw iae;
        } catch (ServiceRuntimeException e) {
            throw e;
        } catch (Exception e) {
            throw new ServiceRuntimeException(e.getMessage(), e);
        }
    }

    /* ******************** Contribution for issue TUSCANY-2281 ******************** */

    public CompositeContext getCompositeContext() {
        return compositeContext;
    }

    public ExtensionPointRegistry getExtensionPointRegistry() {
        return getCompositeContext().getExtensionPointRegistry();
    }

}
