/*
 * 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.builder.impl;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.logging.Logger;

import javax.xml.namespace.QName;

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.ComponentReference;
import org.apache.tuscany.sca.assembly.ComponentService;
import org.apache.tuscany.sca.assembly.ComponentType;
import org.apache.tuscany.sca.assembly.Composite;
import org.apache.tuscany.sca.assembly.CompositeReference;
import org.apache.tuscany.sca.assembly.CompositeService;
import org.apache.tuscany.sca.assembly.Contract;
import org.apache.tuscany.sca.assembly.Multiplicity;
import org.apache.tuscany.sca.assembly.Reference;
import org.apache.tuscany.sca.assembly.SCABinding;
import org.apache.tuscany.sca.assembly.SCABindingFactory;
import org.apache.tuscany.sca.assembly.Service;
import org.apache.tuscany.sca.assembly.builder.BuilderContext;
import org.apache.tuscany.sca.assembly.builder.BuilderExtensionPoint;
import org.apache.tuscany.sca.assembly.builder.ContractBuilder;
import org.apache.tuscany.sca.assembly.builder.Messages;
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.definitions.Definitions;
import org.apache.tuscany.sca.interfacedef.Compatibility;
import org.apache.tuscany.sca.interfacedef.IncompatibleInterfaceContractException;
import org.apache.tuscany.sca.interfacedef.InterfaceContract;
import org.apache.tuscany.sca.interfacedef.InterfaceContractMapper;
import org.apache.tuscany.sca.interfacedef.java.JavaInterfaceContract;
import org.apache.tuscany.sca.monitor.Monitor;
import org.apache.tuscany.sca.policy.ExtensionType;
import org.apache.tuscany.sca.policy.PolicySubject;

/**
 * @version $Rev$ $Date$
 */

// TODO - really implementation.composite component type builder - CompositeComponentTypeBuilder?

public class CompositeComponentTypeBuilderImpl {
    private static final Logger logger = Logger.getLogger(CompositeComponentTypeBuilderImpl.class.getName());

    protected static final String SCA11_NS = "http://docs.oasis-open.org/ns/opencsa/sca/200912";
    protected static final String BINDING_SCA = "binding.sca";
    protected static final QName BINDING_SCA_QNAME = new QName(SCA11_NS, BINDING_SCA);

    private ComponentBuilderImpl componentBuilder;
    private AssemblyFactory assemblyFactory;
    private SCABindingFactory scaBindingFactory;
    private InterfaceContractMapper interfaceContractMapper;
    private BuilderExtensionPoint builders;
    private ContractBuilder contractBuilder;

    public CompositeComponentTypeBuilderImpl(ExtensionPointRegistry registry) {
        UtilityExtensionPoint utilities = registry.getExtensionPoint(UtilityExtensionPoint.class);

        FactoryExtensionPoint modelFactories = registry.getExtensionPoint(FactoryExtensionPoint.class);
        assemblyFactory = modelFactories.getFactory(AssemblyFactory.class);
        scaBindingFactory = modelFactories.getFactory(SCABindingFactory.class);

        interfaceContractMapper = utilities.getUtility(InterfaceContractMapper.class);
        builders = registry.getExtensionPoint(BuilderExtensionPoint.class);
        contractBuilder = builders.getContractBuilder();
    }

    public void setComponentBuilder(ComponentBuilderImpl componentBuilder) {
        this.componentBuilder = componentBuilder;
    }

    /**
     * Calculate the component type for the provided implementation
     * 
     * @param implementation
     * @return component type
     */
    public void createComponentType(Component outerComponent, Composite composite, BuilderContext context) {

        Monitor monitor = context.getMonitor();
        monitor.pushContext("Composite: " + composite.getName().toString());
        
        try {
            // first make sure that each child component has been properly configured based
            // on its own component type
            for (Component component : composite.getComponents()) {
    
                // Check for duplicate component names
                if (component != composite.getComponent(component.getName())) {
                    Monitor.error(monitor, 
                                  this, 
                                  Messages.ASSEMBLY_VALIDATION, 
                                  "DuplicateComponentName", 
                                  composite.getName().toString(), 
                                  component.getName());
                }
    
                // do any work we need to do before we configure the component
                // Anything that needs to be pushed down the promotion
                // hierarchy must be done before we configure the component
    
                // Push down the autowire flag from the composite to components
                if (component.getAutowire() == null) {
                    component.setAutowire(composite.getAutowire());
                }
    
                // configure the component from its component type
                componentBuilder.configureComponentFromComponentType(outerComponent, composite, component, context);
            }
    
            // create the composite component type based on the promoted artifacts
            // from the components that it contains
    
            // index all the components, services and references in the
            // component type so that they are easy to find
            Map<String, Component> components = new HashMap<String, Component>();
            Map<String, ComponentService> componentServices = new HashMap<String, ComponentService>();
            Map<String, ComponentReference> componentReferences = new HashMap<String, ComponentReference>();
            indexComponentsServicesAndReferences(composite, components, componentServices, componentReferences);
    
            // services
            calculateServices(composite, components, componentServices, context);
    
            // references
            calculateReferences(composite, components, componentReferences, context);
    
            // properties
            // Properties on the composite component are unaffected by properties 
            // on child components. Instead child component properties might take their
            // values from composite properties. Hence there is nothing to do here.
            //calculateProperties(composite, components);
        
        } finally {
            monitor.popContext();
        } 
    }

    /**
     * Index components, services and references inside a composite.
     * 
     * @param composite
     * @param components
     * @param componentServices
     * @param componentReferences
     */
    private void indexComponentsServicesAndReferences(Composite composite,
                                                      Map<String, Component> components,
                                                      Map<String, ComponentService> componentServices,
                                                      Map<String, ComponentReference> componentReferences) {

        for (Component component : composite.getComponents()) {

            // Index components by name
            components.put(component.getName(), component);

            ComponentService nonCallbackService = null;
            int nonCallbackServices = 0;
            for (ComponentService componentService : component.getServices()) {

                // Index component services by component name / service name
                String uri = component.getName() + '/' + componentService.getName();
                componentServices.put(uri, componentService);

                // count how many non-callback services there are
                // if there is only one the component name also acts as the service name
                if (!componentService.isForCallback()) {

                    // Check how many non callback non-promoted services we have
                    if (nonCallbackServices == 0) {
                        nonCallbackService = componentService;
                    }
                    nonCallbackServices++;
                }
            }

            if (nonCallbackServices == 1) {
                // If we have a single non callback service, index it by
                // component name as well
                componentServices.put(component.getName(), nonCallbackService);
            }

            // Index references by component name / reference name
            for (ComponentReference componentReference : component.getReferences()) {
                String uri = component.getName() + '/' + componentReference.getName();
                componentReferences.put(uri, componentReference);
            }
        }
    }

    /**
     * Connect the services in the component type to the component services that
     * they promote
     * 
     * @param componentType
     * @param component
     */
    private void calculateServices(ComponentType componentType,
                                   Map<String, Component> components,
                                   Map<String, ComponentService> componentServices,
                                   BuilderContext context) {
        
        Monitor monitor = context.getMonitor();

        // Connect this component type's services to the 
        // services from child components which it promotes
        connectPromotedServices(componentType, components, componentServices, monitor);

        // look at each component type service in turn and 
        // calculate its configuration based on OASIS rules
        for (Service service : componentType.getServices()) {
            CompositeService compositeService = (CompositeService)service;
            ComponentService promotedComponentService = compositeService.getPromotedService();

            // promote interface contracts
            calculatePromotedServiceInterfaceContract(compositeService, promotedComponentService, monitor);

            // promote bindings
            calculatePromotedBindings(compositeService, promotedComponentService);

            componentBuilder.policyBuilder.configure(compositeService, context);
        }
    }

    /**
     * Connect the references in the component type to the component references that
     * they promote
     * 
     * @param componentType
     * @param component
     */
    private void calculateReferences(ComponentType componentType,
                                     Map<String, Component> components,
                                     Map<String, ComponentReference> componentReferences, 
                                     BuilderContext context) {
        Monitor monitor = context.getMonitor();
        // Connect this component type's references to the 
        // references from child components which it promotes
        connectPromotedReferences(componentType, components, componentReferences, monitor);

        // look at each component type reference in turn and 
        // calculate its configuration based on OASIS rules
        for (Reference reference : componentType.getReferences()) {
            CompositeReference compositeReference = (CompositeReference)reference;
            List<ComponentReference> promotedReferences = compositeReference.getPromotedReferences();

            for (ComponentReference promotedComponentReference : promotedReferences) {
                
                // promote multiplicity
                reconcileReferenceMultiplicity(componentType, compositeReference, promotedComponentReference, monitor);
                
                // check nonOverridable
                validateNonOverridable(componentType, compositeReference, promotedComponentReference, monitor);

                // promote interface contracts
                calculatePromotedReferenceInterfaceContract(compositeReference, promotedComponentReference, monitor);

                // promote bindings
                // Don't need to promote reference bindings as any lower level binding will
                // already be targeting the correct service without need for promotion
                //calculatePromotedBindings(compositeReference, promotedComponentReference);
            }
            
            componentBuilder.policyBuilder.configure(compositeReference, context);
        }
    }

    /**
     * Connect the services in the component type to the component services that
     * they promote
     * 
     * @param componentType
     * @param component
     */
    private void connectPromotedServices(ComponentType componentType,
                                         Map<String, Component> components,
                                         Map<String, ComponentService> componentServices,
                                         Monitor monitor) {

        for (Service service : componentType.getServices()) {
            // Connect composite (component type) services to the component services 
            // that they promote 
            CompositeService compositeService = (CompositeService)service;
            ComponentService componentService = compositeService.getPromotedService();
            if (componentService != null && componentService.isUnresolved()) {
                // get the name of the promoted component/service
                String promotedComponentName = compositeService.getPromotedComponent().getName();
                String promotedServiceName;
                if (componentService.getName() != null) {
                    if (compositeService.isForCallback()) {
                        // For callbacks the name already has the form "componentName/servicename"
                        promotedServiceName = componentService.getName();
                    } else {
                        promotedServiceName = promotedComponentName + '/' + componentService.getName();
                    }
                } else {
                    promotedServiceName = promotedComponentName;
                }

                // find the promoted service
                ComponentService promotedService = componentServices.get(promotedServiceName);

                if (promotedService != null) {

                    // Point to the resolved component
                    Component promotedComponent = components.get(promotedComponentName);
                    compositeService.setPromotedComponent(promotedComponent);

                    // Point to the resolved component service
                    compositeService.setPromotedService(promotedService);
                } else {
                    Monitor.error(monitor,
                                  this,
                                  Messages.ASSEMBLY_VALIDATION,
                                  "PromotedServiceNotFound",
                                  ((Composite)componentType).getName().toString(),
                                  promotedServiceName);
                }
            }
        }
    }

    /**
     * Connect the references in the component type to the component references that
     * they promote
     * 
     * @param componentType
     * @param component
     */
    private void connectPromotedReferences(ComponentType componentType,
                                           Map<String, Component> components,
                                           Map<String, ComponentReference> componentReferences,
                                           Monitor monitor) {

        // Connect composite (component type) references to the component references that they promote
        for (Reference reference : componentType.getReferences()) {
            CompositeReference compositeReference = (CompositeReference)reference;
            List<ComponentReference> promotedReferences = compositeReference.getPromotedReferences();
            for (int i = 0, n = promotedReferences.size(); i < n; i++) {
                ComponentReference componentReference = promotedReferences.get(i);
                if (componentReference.isUnresolved()) {
                    String componentReferenceName = componentReference.getName();
                    componentReference = componentReferences.get(componentReferenceName);
                    if (componentReference != null) {
                        // Set the promoted component
                        Component promotedComponent = compositeReference.getPromotedComponents().get(i);
                        promotedComponent = components.get(promotedComponent.getName());
                        compositeReference.getPromotedComponents().set(i, promotedComponent);

                        componentReference.setPromoted(true);

                        // Point to the resolved component reference
                        promotedReferences.set(i, componentReference);
                    } else {
                        Monitor.error(monitor,
                                      this,
                                      Messages.ASSEMBLY_VALIDATION,
                                      "PromotedReferenceNotFound",
                                      ((Composite)componentType).getName().toString(),
                                      componentReferenceName);
                    }
                }
            }
        }
    }

    /**
     * Create a default SCA binding in the case that no binding
     * is specified by the user
     * 
     * @param contract
     * @param definitions
     */
    protected void createSCABinding(Contract contract, Definitions definitions) {

        SCABinding scaBinding = scaBindingFactory.createSCABinding();
        scaBinding.setName(contract.getName());

        if (definitions != null) {
            for (ExtensionType attachPointType : definitions.getBindingTypes()) {
                if (attachPointType.getType().equals(BINDING_SCA_QNAME)) {
                    ((PolicySubject)scaBinding).setExtensionType(attachPointType);
                }
            }
        }

        contract.getBindings().add(scaBinding);
        contract.setOverridingBindings(false);
    }

    /**
     * The following methods implement rules that the OASIS specification defined explicitly
     * to control how configuration from a component type is inherited by a component
     */

    /**
     * Interface contract from higher in the implementation hierarchy takes precedence. 
     * When it comes to checking compatibility the top level service interface is a 
     * subset of the promoted service interface so treat the top level interface as
     * the source
     * 
     * @param topContract the top contract 
     * @param bottomContract the bottom contract
     */
    private void calculatePromotedServiceInterfaceContract(Service topContract, Service bottomContract, Monitor monitor) {
        // Use the interface contract from the bottom level contract if
        // none is specified on the top level contract
        InterfaceContract topInterfaceContract = topContract.getInterfaceContract();
        InterfaceContract bottomInterfaceContract = bottomContract.getInterfaceContract();

        if (topInterfaceContract == null) {
            topContract.setInterfaceContract(bottomInterfaceContract);
        } else if (bottomInterfaceContract != null) {
            // Check that the top and bottom interface contracts are compatible
            boolean isCompatible = true;
            String incompatibilityReason = "";
            try{
                isCompatible = checkSubsetCompatibility(topInterfaceContract, bottomInterfaceContract);
            } catch (IncompatibleInterfaceContractException ex){
                isCompatible = false;
                incompatibilityReason = ex.getMessage();
            }
            if (!isCompatible) {
                Monitor.error(monitor,
                              this,
                              Messages.ASSEMBLY_VALIDATION,
                              "ServiceInterfaceNotSubSet",
                              topContract.getName(),
                              incompatibilityReason);
            }
            
            // TODO - there is an issue with the following code if the 
            //        contracts of of different types. Need to use the 
            //        normalized form
            
            // fix up the forward interface based on the promoted component
            // Someone might have manually specified a callback interface but
            // left out the forward interface
            if (topInterfaceContract.getInterface() == null){
                topInterfaceContract.setInterface(bottomInterfaceContract.getInterface());
            }              
            
            // fix up the callback interface based on the promoted component
            // Someone might have manually specified a forward interface but
            // left out the callback interface
            if (topInterfaceContract.getCallbackInterface() == null){
                topInterfaceContract.setCallbackInterface(bottomInterfaceContract.getCallbackInterface());
            }
        }
    }
    
    /**
     * Interface contract from higher in the implementation hierarchy takes precedence. 
     * When it comes to checking compatibility the top level reference interface is a 
     * superset of the promoted reference interface so treat the promoted
     * (bottom) interface as the source
     * 
     * @param topContract the top contract 
     * @param bottomContract the bottom contract
     */    
    private void calculatePromotedReferenceInterfaceContract(Reference topContract, Reference bottomContract, Monitor monitor) {
        // Use the interface contract from the bottom level contract if
        // none is specified on the top level contract
        InterfaceContract topInterfaceContract = topContract.getInterfaceContract();
        InterfaceContract bottomInterfaceContract = bottomContract.getInterfaceContract();

        if (topInterfaceContract == null) {
            topContract.setInterfaceContract(bottomInterfaceContract);
        } else if (bottomInterfaceContract != null) {
            // Check that the top and bottom interface contracts are compatible
            boolean isCompatible = true;
            String incompatibilityReason = "";
            try{
                isCompatible = checkSubsetCompatibility(bottomInterfaceContract, topInterfaceContract);
            } catch (IncompatibleInterfaceContractException ex){
                isCompatible = false;
                incompatibilityReason = ex.getMessage();
            }
            if (!isCompatible) {
                Monitor.error(monitor,
                              this,
                              Messages.ASSEMBLY_VALIDATION,
                              "ReferenceInterfaceNotSubSet",
                              topContract.getName(),
                              incompatibilityReason);
            }
            
            // TODO - there is an issue with the following code if the 
            //        contracts of of different types. Need to use the 
            //        normalized form
            
            // fix up the forward interface based on the promoted component
            // Someone might have manually specified a callback interface but
            // left out the forward interface
            if (topInterfaceContract.getInterface() == null){
                topInterfaceContract.setInterface(bottomInterfaceContract.getInterface());
            }              
            
            // fix up the callback interface based on the promoted component
            // Someone might have manually specified a forward interface but
            // left out the callback interface
            if (topInterfaceContract.getCallbackInterface() == null){
                topInterfaceContract.setCallbackInterface(bottomInterfaceContract.getCallbackInterface());
            }            
        }
    }    

    /**
     * Bindings from higher in the implementation hierarchy take precedence
     * 
     * @param compositeService
     * @param promotedComponentService
     */
    private void calculatePromotedBindings(CompositeService compositeService, ComponentService promotedComponentService) {
        // forward bindings
        if (compositeService.getBindings().isEmpty()) {
            for (Binding binding : promotedComponentService.getBindings()) {
                try {
                    compositeService.getBindings().add((Binding)binding.clone());
                } catch (CloneNotSupportedException ex) {
                    // this binding can't be used in the promoted service
                }
            }
        }

        if (compositeService.getBindings().isEmpty()) {
            createSCABinding(compositeService, null);
        }

        // callback bindings
        if (promotedComponentService.getCallback() != null) {
            if (compositeService.getCallback() != null) {
                compositeService.getCallback().getBindings().clear();
            } else {
                compositeService.setCallback(assemblyFactory.createCallback());
            }

            for (Binding binding : promotedComponentService.getCallback().getBindings()) {
                try {
                    compositeService.getCallback().getBindings().add((Binding)binding.clone());
                } catch (CloneNotSupportedException ex) {
                    // this binding can't be used in the promoted service
                }
            }
        }
    }
    
    private void reconcileReferenceMultiplicity(ComponentType componentType,
                                                Reference compositeReference, 
                                                Reference promotedComponentReference,
                                                Monitor monitor) {
        if (compositeReference.getMultiplicity() != null) {
            if (!isValidMultiplicityOverride(promotedComponentReference.getTargets().size() > 0,
                                             promotedComponentReference.getMultiplicity(), 
                                             compositeReference.getMultiplicity())) {
                Monitor.error(monitor, 
                              this, 
                              Messages.ASSEMBLY_VALIDATION,
                              "CompositeReferenceIncompatibleMultiplicity", 
                              componentType.getURI(), 
                              compositeReference.getName(),
                              promotedComponentReference.getName());
            }
        } else {
            compositeReference.setMultiplicity(promotedComponentReference.getMultiplicity());
        }
    }    
    
    private boolean isValidMultiplicityOverride(boolean componentRefHasTarget,
                                                Multiplicity componentRefMul, 
                                                Multiplicity compositeRefMul) {
        if ((componentRefMul != null) && 
            (compositeRefMul != null) &&
             componentRefMul != compositeRefMul) {
            if (componentRefHasTarget){
                switch (componentRefMul) {
                    case ZERO_ONE:
                        return compositeRefMul == Multiplicity.ZERO_ONE || 
                               compositeRefMul == Multiplicity.ONE_ONE;
                    case ONE_ONE:
                        return compositeRefMul == Multiplicity.ZERO_ONE || 
                               compositeRefMul == Multiplicity.ONE_ONE;                      
                    case ZERO_N:
                        return true;
                    case ONE_N:
                        return true;
                    default:
                        return false;
                }
            } else {
                switch (componentRefMul) {
                    case ZERO_ONE:
                        return compositeRefMul == Multiplicity.ONE_ONE;
                    case ONE_ONE:
                        return compositeRefMul == Multiplicity.ONE_ONE;                      
                    case ZERO_N:
                        return true;
                    case ONE_N:
                        return compositeRefMul == Multiplicity.ONE_ONE || 
                               compositeRefMul == Multiplicity.ONE_N;

                    default:
                        return false;
                }
            }
        } else {
            return true;
        }
    }  
    
    /**
     * ASM50042 - Checks that if a component reference with multiplicity="1..1" is marked
     * as nonOveridable then there are no composite references that promote it
     * 
     * @param componentType
     * @param compositeReference
     * @param promotedComponentReference
     * @param monitor
     */
    private void validateNonOverridable(ComponentType componentType,
                                        Reference compositeReference, 
                                        Reference promotedComponentReference,
                                        Monitor monitor){
        if ((promotedComponentReference.getMultiplicity() == Multiplicity.ONE_ONE) &&
            (((ComponentReference)promotedComponentReference)).isNonOverridable() == true) {
            Monitor.error(monitor, 
                    this, 
                    Messages.ASSEMBLY_VALIDATION,
                    "CompositeReferencePromotesNonOverridableReference", 
                    componentType.getURI(), 
                    compositeReference.getName(),
                    promotedComponentReference.getName());
        }
    }
    
    /**
     * A local wrapper for the interface contract mapper as we need to normalize the 
     * interface contracts if appropriate and the mapper doesn't have the right
     * dependencies to be able to do it. 
     * 
     * Sometimes the two interfaces can be presented using different IDLs, for example
     * Java and WSDL. In this case interfaces are converted so that they are both WSDL1.1 interfaces
     * and they are then compared. The generated WSDL is cached on the interface object for 
     * any subsequent matching
     * 
     * @param contractA
     * @param contractB
     * @return true if the interface contracts match
     */
    private boolean checkSubsetCompatibility(InterfaceContract contractA, InterfaceContract contractB)
        throws IncompatibleInterfaceContractException {
        
        if (contractA.getClass() != contractB.getClass()) {
           
            if (contractA instanceof JavaInterfaceContract){
                contractBuilder.build(contractA, null);
                contractA = ((JavaInterfaceContract)contractA).getNormalizedWSDLContract();
            } 
            
            if (contractB instanceof JavaInterfaceContract){
                contractBuilder.build(contractB, null);
                contractB = ((JavaInterfaceContract)contractB).getNormalizedWSDLContract();
            }            
        }   
        
        return interfaceContractMapper.checkCompatibility(contractA, 
                                                          contractB, 
                                                          Compatibility.SUBSET, 
                                                          false, 
                                                          false);
    }    
    
} //end class
