/*
 * 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.databinding.transformers;

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

import org.apache.tuscany.sca.databinding.DataBinding;
import org.apache.tuscany.sca.databinding.Mediator;
import org.apache.tuscany.sca.databinding.PullTransformer;
import org.apache.tuscany.sca.databinding.TransformationContext;
import org.apache.tuscany.sca.databinding.TransformationException;
import org.apache.tuscany.sca.databinding.WrapperHandler;
import org.apache.tuscany.sca.databinding.impl.BaseTransformer;
import org.apache.tuscany.sca.interfacedef.DataType;
import org.apache.tuscany.sca.interfacedef.Operation;
import org.apache.tuscany.sca.interfacedef.util.ElementInfo;
import org.apache.tuscany.sca.interfacedef.util.WrapperInfo;
import org.apache.tuscany.sca.interfacedef.util.XMLType;
import org.osoa.sca.annotations.Reference;

/**
 * This is a special transformer to transform the input from one IDL to the
 * other one
 *
 * @version $Rev$ $Date$
 */
public class Input2InputTransformer extends BaseTransformer<Object[], Object[]> implements
    PullTransformer<Object[], Object[]> {
    private static final Logger logger = Logger.getLogger(Input2InputTransformer.class.getName());

    protected Mediator mediator;

    public Input2InputTransformer() {
        super();
    }

    @Override
    public String getSourceDataBinding() {
        return DataBinding.IDL_INPUT;
    }

    @Override
    public String getTargetDataBinding() {
        return DataBinding.IDL_INPUT;
    }

    /**
     * @param mediator the mediator to set
     */
    @Reference
    public void setMediator(Mediator mediator) {
        this.mediator = mediator;
    }

    /**
     * @see org.apache.tuscany.sca.databinding.impl.BaseTransformer#getSourceType()
     */
    @Override
    protected Class<Object[]> getSourceType() {
        return Object[].class;
    }

    /**
     * @see org.apache.tuscany.sca.databinding.impl.BaseTransformer#getTargetType()
     */
    @Override
    protected Class<Object[]> getTargetType() {
        return Object[].class;
    }

    /**
     * @see org.apache.tuscany.sca.databinding.Transformer#getWeight()
     */
    @Override
    public int getWeight() {
        return 10000;
    }

    /**
     * Match the structure of the wrapper element. If it matches, then we can do
     * wrapper to wrapper transformation. Otherwise, we do child to child.
     * @param w1
     * @param w2
     * @return
     */
    private boolean matches(WrapperInfo w1, WrapperInfo w2) {
        if (w1 == null || w2 == null) {
            return false;
        }
        if (!w1.getWrapperElement().equals(w2.getWrapperElement())) {
            return false;
        }

        // Compare the child elements
        List<ElementInfo> list1 = w1.getChildElements();
        List<ElementInfo> list2 = w2.getChildElements();
        if (list1.size() != list2.size()) {
            return false;
        }
        // FXIME: [rfeng] At this point, the J2W generates local elments under the namespace
        // of the interface instead of "". We only compare the local parts only to work around
        // the namespace mismatch
        for (int i = 0; i < list1.size(); i++) {
            String n1 = list1.get(i).getQName().getLocalPart();
            String n2 = list2.get(i).getQName().getLocalPart();

            // TUSCANY-3298: In the following situation:
            //  1. The child is a java.util.Map type
            //  2. The child's name is a Java keyword (e.g., return)
            //  3. Tuscany is using a generated JAXB wrapper class for WSDL generation
            // the Java to WSDL generation process results in the WSDL element name
            // having a leading underscore added to the actual element name.  This is
            // because of a known JAXB issue that prevents the @XmlElement annotation
            // being used on a java.util.Map type property field in the wrapper bean
            // (see https://jaxb.dev.java.net/issues/show_bug.cgi?id=268).
            // To prevent the compatibility match from failing in this situation,
            // we strip any leading underscore before doing the comparison.
            if (!stripLeadingUnderscore(n1).equals(stripLeadingUnderscore(n2))) {
                return false;
            }
        }
        return true;
    }

    private static String stripLeadingUnderscore(String name) {
        return name.startsWith("_") ? name.substring(1) : name;
    }

    @SuppressWarnings("unchecked")
    public Object[] transform(Object[] source, TransformationContext context) {
        // Check if the source operation is wrapped
        DataType<List<DataType>> sourceType = context.getSourceDataType();
        Operation sourceOp = context.getSourceOperation();
        boolean sourceWrapped = sourceOp != null && sourceOp.isInputWrapperStyle() && sourceOp.getInputWrapper() != null;
        boolean sourceBare = sourceOp != null && !sourceOp.isInputWrapperStyle() && sourceOp.getInputWrapper() == null;

        // Find the wrapper handler for source data
        WrapperHandler sourceWrapperHandler = null;
        String sourceDataBinding = getDataBinding(sourceOp);
        sourceWrapperHandler = getWrapperHandler(sourceDataBinding, sourceWrapped);

        // Check if the target operation is wrapped
        DataType<List<DataType>> targetType = context.getTargetDataType();
        Operation targetOp = (Operation)context.getTargetOperation();
        boolean targetWrapped = targetOp != null && targetOp.isInputWrapperStyle() && targetOp.getInputWrapper() != null;
        boolean targetBare = targetOp != null && !targetOp.isInputWrapperStyle() && targetOp.getInputWrapper() == null;

        // Find the wrapper handler for target data
        WrapperHandler targetWrapperHandler = null;
        String targetDataBinding = getDataBinding(targetOp);
        targetWrapperHandler = getWrapperHandler(targetDataBinding, targetWrapped);

        if ((!sourceWrapped && !sourceBare) && targetWrapped) {
            // Unwrapped --> Wrapped
            WrapperInfo wrapper = targetOp.getInputWrapper();
            // ElementInfo wrapperElement = wrapper.getInputWrapperElement();

            // Class<?> targetWrapperClass = wrapper != null ? wrapper.getInputWrapperClass() : null;

            if (source == null) {
                // Empty child elements
                Object targetWrapper = targetWrapperHandler.create(targetOp, true);
                return new Object[] {targetWrapper};
            }

            // If the source can be wrapped, wrapped it first
            if (sourceWrapperHandler != null) {
                WrapperInfo sourceWrapperInfo = sourceOp.getInputWrapper();
                DataType sourceWrapperType = sourceWrapperInfo != null ? sourceWrapperInfo.getWrapperType() : null;

                // We only do wrapper to wrapper transformation if the source has a wrapper and both sides
                // match by XML structure
                if (sourceWrapperType != null && matches(sourceOp.getInputWrapper(), targetOp.getInputWrapper())) {
                    Class<?> sourceWrapperClass = sourceWrapperType.getPhysical();

                    // Create the source wrapper
                    Object sourceWrapper = sourceWrapperHandler.create(sourceOp, true);

                    // Populate the source wrapper
                    if (sourceWrapper != null) {
                        sourceWrapperHandler.setChildren(sourceWrapper,
                                                         source,
                                                         sourceOp,
                                                         true);

                        // Transform the data from source wrapper to target wrapper
                        Object targetWrapper =
                            mediator.mediate(sourceWrapper, sourceWrapperType, targetType.getLogical().get(0), context
                                .getMetadata());
                        return new Object[] {targetWrapper};
                    }
                }
            }
            // Fall back to child by child transformation
            Object targetWrapper = targetWrapperHandler.create(targetOp, true);
            List<DataType> argTypes = wrapper.getUnwrappedInputType().getLogical();
            Object[] targetChildren = new Object[source.length];
            for (int i = 0; i < source.length; i++) {
                // ElementInfo argElement = wrapper.getInputChildElements().get(i);
                DataType<XMLType> argType = argTypes.get(i);
                targetChildren[i] =
                    mediator.mediate(source[i], sourceType.getLogical().get(i), argType, context.getMetadata());
            }
            targetWrapperHandler.setChildren(targetWrapper,
                                             targetChildren,
                                             targetOp,
                                             true);
            return new Object[] {targetWrapper};

        } else if (sourceWrapped && (!targetWrapped && !targetBare)) {
            // Wrapped to Unwrapped
            Object sourceWrapper = source[0];
            Object[] target = null;

            // List<ElementInfo> childElements = sourceOp.getWrapper().getInputChildElements();
            if (targetWrapperHandler != null) {
                // ElementInfo wrapperElement = sourceOp.getWrapper().getInputWrapperElement();
                // FIXME: This is a workaround for the wsdless support as it passes in child elements
                // under the wrapper that only matches by position
                if (sourceWrapperHandler.isInstance(sourceWrapper, sourceOp, true)) {

                    WrapperInfo targetWrapperInfo = targetOp.getInputWrapper();
                    DataType targetWrapperType =
                        targetWrapperInfo != null ? targetWrapperInfo.getWrapperType() : null;
                    if (targetWrapperType != null && matches(sourceOp.getInputWrapper(), targetOp.getInputWrapper())) {
                        Object targetWrapper =
                            mediator.mediate(sourceWrapper, sourceType.getLogical().get(0), targetWrapperType, context
                                .getMetadata());
                        target = targetWrapperHandler.getChildren(targetWrapper, targetOp, true).toArray();
                        return target;
                    }
                }
            }
            Object[] sourceChildren = sourceWrapperHandler.getChildren(sourceWrapper, sourceOp, true).toArray();
            target = new Object[sourceChildren.length];
            for (int i = 0; i < sourceChildren.length; i++) {
                DataType<XMLType> childType = sourceOp.getInputWrapper().getUnwrappedInputType().getLogical().get(i);
                target[i] =
                    mediator.mediate(sourceChildren[i], childType, targetType.getLogical().get(i), context
                        .getMetadata());
            }
            return target;
        } else {
            // Assuming wrapper to wrapper conversion can be handled here as well
            Object[] newArgs = new Object[source.length];
            for (int i = 0; i < source.length; i++) {
                Object child =
                    mediator.mediate(source[i], sourceType.getLogical().get(i), targetType.getLogical().get(i), context
                        .getMetadata());
                newArgs[i] = child;
            }
            return newArgs;
        }
    }

    private WrapperHandler getWrapperHandler(String dataBindingId, boolean required) {
        WrapperHandler wrapperHandler = null;
        if (dataBindingId != null) {
            DataBinding dataBinding = mediator.getDataBindings().getDataBinding(dataBindingId);
            wrapperHandler = dataBinding == null ? null : dataBinding.getWrapperHandler();
        }
        if (wrapperHandler == null && required) {
            throw new TransformationException("No wrapper handler is provided for databinding: " + dataBindingId);
        }
        return wrapperHandler;
    }

    private String getDataBinding(Operation operation) {
        WrapperInfo wrapper = operation.getInputWrapper();
        if (wrapper != null) {
            return wrapper.getDataBinding();
        } else {
            return null;
        }
    }

}
