/*
 * 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;

import java.io.IOException;
import java.io.Reader;
import java.io.StringReader;
import java.io.StringWriter;
import java.io.Writer;
import java.util.ArrayList;
import java.util.List;

import javax.xml.namespace.QName;
import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.XMLOutputFactory;
import javax.xml.stream.XMLStreamReader;
import javax.xml.stream.XMLStreamWriter;

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.Composite;
import org.apache.tuscany.sca.assembly.Multiplicity;
import org.apache.tuscany.sca.assembly.OptimizableBinding;
import org.apache.tuscany.sca.assembly.Reference;
import org.apache.tuscany.sca.assembly.Service;
import org.apache.tuscany.sca.contribution.processor.StAXArtifactProcessor;
import org.apache.tuscany.sca.contribution.processor.StAXArtifactProcessorExtensionPoint;
import org.apache.tuscany.sca.contribution.resolver.ModelResolver;
import org.apache.tuscany.sca.core.assembly.CompositeActivator;
import org.apache.tuscany.sca.core.invocation.ThreadMessageContext;
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.JavaInterfaceFactory;
import org.apache.tuscany.sca.invocation.Message;
import org.apache.tuscany.sca.runtime.EndpointReference;
import org.apache.tuscany.sca.runtime.RuntimeComponent;
import org.apache.tuscany.sca.runtime.RuntimeComponentReference;
import org.apache.tuscany.sca.runtime.RuntimeComponentService;
import org.osoa.sca.ServiceRuntimeException;

/**
 * @version $Rev$ $Date$
 */
public class ComponentContextHelper {

    private final AssemblyFactory assemblyFactory;
    private final JavaInterfaceFactory javaInterfaceFactory;
    private final StAXArtifactProcessorExtensionPoint staxProcessors;

    /**
     * @param assemblyFactory The factory to create assembly models
     * @param processors The extension point for StAX artifact processors
     */
    public ComponentContextHelper(AssemblyFactory assemblyFactory,
                                  JavaInterfaceFactory javaInterfaceFactory,
                                  StAXArtifactProcessorExtensionPoint processors) {
        this.assemblyFactory = assemblyFactory;
        this.javaInterfaceFactory = javaInterfaceFactory;
        this.staxProcessors = processors;
    }

    /**
     * Create a self-reference for a component service
     * @param component
     * @param service
     * @throws CloneNotSupportedException 
     * @throws InvalidInterfaceException 
     */
    public ComponentReference createSelfReference(Component component,
                                                  ComponentService service,
                                                  Class<?> businessInterface) throws CloneNotSupportedException,
        InvalidInterfaceException {
        ComponentReference componentReference = assemblyFactory.createComponentReference();
        componentReference.setName("$self$." + service.getName());
        for (Binding binding : service.getBindings()) {
            if (binding instanceof OptimizableBinding) {
                OptimizableBinding optimizableBinding = (OptimizableBinding)((OptimizableBinding)binding).clone();
                optimizableBinding.setTargetBinding(binding);
                optimizableBinding.setTargetComponent(component);
                optimizableBinding.setTargetComponentService(service);
                componentReference.getBindings().add(optimizableBinding);
            } else {
                componentReference.getBindings().add(binding);
            }
        }

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

        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);
        return componentReference;
    }

    /**
     * @param interfaceContract
     * @param businessInterface
     * @return
     * @throws CloneNotSupportedException
     * @throws InvalidInterfaceException
     */
    private InterfaceContract getInterfaceContract(InterfaceContract interfaceContract, Class<?> businessInterface)
        throws CloneNotSupportedException, InvalidInterfaceException {
        Interface interfaze = interfaceContract.getInterface();
        boolean compatible = false;
        if (interfaze instanceof JavaInterface) {
            Class<?> cls = ((JavaInterface)interfaze).getJavaClass();
            if (businessInterface.isAssignableFrom(cls)) {
                compatible = true;
            }
        }
        if (!compatible) {
            // The interface is not assignable from the interface contract
            interfaceContract = (InterfaceContract)interfaceContract.clone();
            interfaceContract.setInterface(javaInterfaceFactory.createJavaInterface(businessInterface));
        }

        return interfaceContract;
    }

    /**
     * Bind a component reference to a component service
     * @param <B>
     * @param businessInterface
     * @param reference
     * @param service
     * @return
     * @throws CloneNotSupportedException
     * @throws InvalidInterfaceException
     */
    public RuntimeComponentReference bindComponentReference(Class<?> businessInterface,
                                                            RuntimeComponentReference reference,
                                                            RuntimeComponent component,
                                                            RuntimeComponentService service)
        throws CloneNotSupportedException, InvalidInterfaceException {
        RuntimeComponentReference ref = (RuntimeComponentReference)reference.clone();
        InterfaceContract interfaceContract = reference.getInterfaceContract();
        Reference componentTypeReference = reference.getReference();
        if (componentTypeReference != null && componentTypeReference.getInterfaceContract() != null) {
            interfaceContract = componentTypeReference.getInterfaceContract();
        }
        InterfaceContract refInterfaceContract = getInterfaceContract(interfaceContract, businessInterface);
        if (refInterfaceContract != interfaceContract) {
            ref = (RuntimeComponentReference)reference.clone();
            ref.setInterfaceContract(interfaceContract);
        }
        ref.setComponent(component);
        ref.getTargets().add(service);
        ref.getBindings().clear();
        for (Binding binding : service.getBindings()) {
            if (binding instanceof OptimizableBinding) {
                OptimizableBinding optimizableBinding = (OptimizableBinding)((OptimizableBinding)binding).clone();
                optimizableBinding.setTargetBinding(binding);
                optimizableBinding.setTargetComponent(component);
                optimizableBinding.setTargetComponentService(service);
                ref.getBindings().add(optimizableBinding);
            } else {
                ref.getBindings().add(binding);
            }
        }
        return ref;
    }

    public void write(Component component, ComponentReference reference, Writer writer) throws IOException {
        write(component, reference, null, writer);
    }

    public void write(Component component, ComponentReference reference, ComponentService service, Writer writer) throws IOException {
        try {
            StAXArtifactProcessor<Composite> processor = staxProcessors.getProcessor(Composite.class);
            Composite composite = assemblyFactory.createComposite();
            composite.setName(new QName("http://tuscany.apache.org/xmlns/sca/1.0", "default"));
            Component comp = assemblyFactory.createComponent();
            comp.setName("default");
            comp.setURI(component.getURI());
            composite.getComponents().add(comp);
            if (reference != null) {
                comp.getReferences().add(reference);
            }
            if (service != null) {
                comp.getServices().add(service);
            }

            XMLOutputFactory outputFactory = XMLOutputFactory.newInstance();
            XMLStreamWriter streamWriter = outputFactory.createXMLStreamWriter(writer);
            processor.write(composite, streamWriter);
        } catch (Exception e) {
            throw new IOException(e.getMessage());
        }
    }

    public String toXML(Component component, ComponentReference reference) throws IOException {
        StringWriter writer = new StringWriter();
        write(component, reference, writer);
        return writer.toString();
    }

    public String toXML(Component component, ComponentService service) throws IOException {
        StringWriter writer = new StringWriter();
        write(component, null, service, writer);
        return writer.toString();
    }

    public RuntimeComponent read(Reader reader) throws IOException {
        try {
            XMLInputFactory inputFactory = XMLInputFactory.newInstance();
            XMLStreamReader streamReader = inputFactory.createXMLStreamReader(reader);
            return read(streamReader);
        } catch (Exception e) {
            throw new IOException(e.getMessage());
        }
    }

    public RuntimeComponent read(XMLStreamReader streamReader) throws IOException {
        try {
            StAXArtifactProcessor<Composite> processor = staxProcessors.getProcessor(Composite.class);
            Composite composite = processor.read(streamReader);
            RuntimeComponent component = (RuntimeComponent)composite.getComponents().get(0);
            return component;
        } catch (Exception e) {
            throw new IOException(e.getMessage());
        }
    }

    public Component fromXML(String xml) throws IOException {
        return read(new StringReader(xml));
    }

    public Component fromXML(XMLStreamReader streamReader) throws IOException {
        return read(streamReader);
    }

    public void resolveInterfaceContract(InterfaceContract interfaceContract, ModelResolver resolver) throws Exception {
        StAXArtifactProcessor processor = staxProcessors.getProcessor(interfaceContract.getClass());
        processor.resolve(interfaceContract, resolver);
    }

    public void resolveBinding(Binding binding, ModelResolver resolver) throws Exception {
        StAXArtifactProcessor processor = staxProcessors.getProcessor(binding.getClass());
        processor.resolve(binding, resolver);
    }

    public Reference createReference(Class<?> businessInterface) throws InvalidInterfaceException {
        InterfaceContract interfaceContract = createJavaInterfaceContract(businessInterface);
        Reference reference = assemblyFactory.createReference();
        reference.setInterfaceContract(interfaceContract);
        return reference;
    }

    private InterfaceContract createJavaInterfaceContract(Class<?> businessInterface) throws InvalidInterfaceException {
        InterfaceContract interfaceContract = javaInterfaceFactory.createJavaInterfaceContract();
        JavaInterface callInterface = javaInterfaceFactory.createJavaInterface(businessInterface);
        interfaceContract.setInterface(callInterface);
        if (callInterface.getCallbackClass() != null) {
            interfaceContract.setCallbackInterface(javaInterfaceFactory.createJavaInterface(
                callInterface.getCallbackClass()));
        }
        return interfaceContract;
    }

    public static RuntimeComponent getCurrentComponent() {
        Message message = ThreadMessageContext.getMessageContext();
        if (message != null) {
            EndpointReference to = message.getTo();
            if (to == null) {
                return null;
            }
            RuntimeComponent component = message.getTo().getComponent();
            return component;
        }
        return null;
    }

    public static CompositeActivator getCurrentCompositeActivator() {
        RuntimeComponent component = getCurrentComponent();
        if (component != null) {
            ComponentContextImpl context = (ComponentContextImpl)component.getComponentContext();
            return context.getCompositeActivator();
        }
        return null;
    }

    public static ComponentContextHelper getCurrentComponentContextHelper() {
        CompositeActivator activator = getCurrentCompositeActivator();
        if (activator != null) {
            return activator.getComponentContextHelper();
        }
        return null;
    }

    /**
     * @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.isCallback()) {
                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;
    }

}
