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

import java.beans.Introspector;
import java.io.StringReader;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.xml.namespace.QName;

import org.apache.tuscany.sca.contribution.resolver.ModelResolver;
import org.apache.tuscany.sca.databinding.XMLTypeHelper;
import org.apache.tuscany.sca.databinding.impl.SimpleTypeMapperImpl;
import org.apache.tuscany.sca.interfacedef.DataType;
import org.apache.tuscany.sca.interfacedef.Interface;
import org.apache.tuscany.sca.interfacedef.Operation;
import org.apache.tuscany.sca.interfacedef.util.JavaXMLMapper;
import org.apache.tuscany.sca.interfacedef.util.TypeInfo;
import org.apache.tuscany.sca.interfacedef.util.WrapperInfo;
import org.apache.tuscany.sca.interfacedef.util.XMLType;
import org.apache.tuscany.sca.xsd.XSDFactory;
import org.apache.tuscany.sca.xsd.XSDefinition;
import org.osoa.sca.ServiceRuntimeException;
import org.w3c.dom.DOMImplementation;
import org.w3c.dom.Document;
import org.w3c.dom.bootstrap.DOMImplementationRegistry;
import org.w3c.dom.ls.DOMImplementationLS;
import org.w3c.dom.ls.LSInput;
import org.w3c.dom.ls.LSParser;

import commonj.sdo.Type;
import commonj.sdo.helper.TypeHelper;
import commonj.sdo.helper.XSDHelper;

public class SDOTypeHelper implements XMLTypeHelper {
    private static final String SCHEMA_NS = "http://www.w3.org/2001/XMLSchema";

    private TypeHelper typeHelper;
    private XSDHelper xsdHelper;
    // private Map<String, List<Type>> xsdTypesMap = new HashMap<String, List<Type>>();
    // private Map<String, List<Type>> typesMap = new HashMap<String, List<Type>>();

    public SDOTypeHelper() {
        super();
        typeHelper = SDOContextHelper.getDefaultHelperContext().getTypeHelper();
        xsdHelper = SDOContextHelper.getDefaultHelperContext().getXSDHelper();
    }

    public TypeInfo getTypeInfo(Class javaType, Object logical) {
        QName xmlType = JavaXMLMapper.getXMLType(javaType);
        if (xmlType != null) {
            return new TypeInfo(xmlType, true, null);
        } else {
            // introspect(javaType, xsdTypesMap, typesMap);
            if (logical instanceof XMLType) {
                xmlType = ((XMLType)logical).getTypeName();
            }
            if (xmlType == null) {
                // TUSCANY-3298: dynamic SDO or collection of dynamic SDO
                return new TypeInfo(SimpleTypeMapperImpl.XSD_ANYTYPE, true, null);
                //xmlType =
                //    new QName(JavaXMLMapper.getNamespace(javaType), Introspector.decapitalize(javaType.getSimpleName()));
            }
            return new TypeInfo(xmlType, false, null);
        }
    }

    private void introspect(Class javaType, Map<String, List<Type>> xsdTypesMap, Map<String, List<Type>> typesMap) {
        Type type = typeHelper.getType(javaType);
        if (type == null) {
            return;
        }
        if (xsdHelper.isXSD(type)) {
            addToMap(xsdTypesMap, type);
        } else {
            addToMap(typesMap, type);
        }
    }

    private void addToMap(Map<String, List<Type>> map, Type type) {
        List<Type> types = map.get(type.getURI());
        if (types == null) {
            types = new ArrayList<Type>();
            map.put(type.getURI(), types);
        }
        if (!types.contains(type)) {
            types.add(type);
        }
    }

    /*
    public List<XSDefinition> getSchemaDefinitions(XSDFactory factory, ModelResolver resolver) {
        List<XSDefinition> definitions = new ArrayList<XSDefinition>();
        generateSDOSchemas(definitions, factory, typesMap);
        addResolvedXSDs(definitions, factory, resolver, xsdTypesMap);
        return definitions;
    }
    */

    private void generateSDOSchemas(List<XSDefinition> definitions, XSDFactory factory, Map<String, List<Type>> map) {
        for (Map.Entry<String, List<Type>> entry : map.entrySet()) {
            List<Type> types = entry.getValue();
            String ns = entry.getKey();
            generateSchema(definitions, factory, types, ns);
        }
    }

    private void generateSchema(List<XSDefinition> definitions, XSDFactory factory, List<Type> types, String ns) {
        String schema = xsdHelper.generate(types);
        DOMImplementationRegistry registry = null;
        try {
            registry = DOMImplementationRegistry.newInstance();
        } catch (Exception e) {
            throw new ServiceRuntimeException(e);
        }
        DOMImplementation impl = registry.getDOMImplementation("XML 3.0");
        DOMImplementationLS ls = (DOMImplementationLS)impl.getFeature("LS", "3.0");
        LSParser parser = ls.createLSParser(DOMImplementationLS.MODE_SYNCHRONOUS, SCHEMA_NS);
        LSInput input = ls.createLSInput();
        input.setCharacterStream(new StringReader(schema));
        Document document = parser.parse(input);
        XSDefinition definition = factory.createXSDefinition();
        definition.setUnresolved(true);
        definition.setDocument(document);
        definition.setNamespace(ns);
        definitions.add(definition);
    }

    private void addResolvedXSDs(List<XSDefinition> definitions,
                                 XSDFactory factory,
                                 ModelResolver resolver,
                                 Map<String, List<Type>> map) {
        for (Map.Entry<String, List<Type>> entry : map.entrySet()) {
            XSDefinition definition = factory.createXSDefinition();
            definition.setUnresolved(true);
            definition.setNamespace(entry.getKey());
            //FIXME: set location URI
            XSDefinition resolved = resolver.resolveModel(XSDefinition.class, definition);
            if (resolved.getSchema() == null) {
                //FIXME: create a checked exception and propagate it back up to the activator
                throw new RuntimeException("No XSD found for namespace " + entry.getKey());
            }
            // make sure all the required types are defined in the resolved schema
            for (Type type : entry.getValue()) {
                String name = xsdHelper.getLocalName(type);
                QName typeName = null;
                if (name.endsWith("_._type")) {
                    // FIXME: Anonymous tyype
                    name = name.substring(0, name.length() - "_._type".length());
                    typeName = new QName(type.getURI(), name);
                    if (resolved.getXmlSchemaElement(typeName) == null) {
                        //FIXME: create a checked exception and propagate it back up to the activator
                        throw new RuntimeException("No XSD found for " + typeName.toString());
                    }
                } else {
                    typeName = new QName(type.getURI(), name);
                    if (resolved.getXmlSchemaType(typeName) == null) {
                        //FIXME: create a checked exception and propagate it back up to the activator
                        throw new RuntimeException("No XSD found for " + typeName.toString());
                    }
                }

            }
            definitions.add(resolved);
        }
    }

    private static List<DataType> getDataTypes(Interface intf) {
        List<DataType> dataTypes = new ArrayList<DataType>();
        for (Operation op : intf.getOperations()) {
            WrapperInfo inputWrapperInfo = op.getInputWrapper();
            WrapperInfo outputWrapperInfo = op.getOutputWrapper();
            if (inputWrapperInfo != null && outputWrapperInfo != null) {
                DataType dt1 = inputWrapperInfo.getWrapperType();
                if (dt1 != null) {
                    dataTypes.add(dt1);
                }
                DataType dt2 = outputWrapperInfo.getWrapperType();
                if (dt2 != null) {
                    dataTypes.add(dt2);
                }
            } else {
                for (DataType dt1 : op.getInputType().getLogical()) {
                    dataTypes.add(dt1);
                }
                DataType dt2 = op.getOutputType();
                if (dt2 != null) {
                    dataTypes.add(dt2);
                }
                for (DataType<DataType> dt3 : op.getFaultTypes()) {
                    DataType dt4 = dt3.getLogical();
                    if (dt4 != null) {
                        dataTypes.add(dt4);
                    }
                }
            }
        }
        return dataTypes;
    }

    public List<XSDefinition> getSchemaDefinitions(XSDFactory factory, ModelResolver resolver, Interface intf) {
        return getSchemaDefinitions(factory, resolver, getDataTypes(intf));
    }

    public List<XSDefinition> getSchemaDefinitions(XSDFactory factory, ModelResolver resolver, List<DataType> dataTypes) {
        Map<String, List<Type>> xsdTypesMap = new HashMap<String, List<Type>>();
        Map<String, List<Type>> typesMap = new HashMap<String, List<Type>>();
        for (DataType d : dataTypes) {
            if (SDODataBinding.NAME.equals(d.getDataBinding())) {
                introspect(d.getPhysical(), xsdTypesMap, typesMap);
            }
        }
        List<XSDefinition> definitions = new ArrayList<XSDefinition>();
        generateSDOSchemas(definitions, factory, typesMap);
        addResolvedXSDs(definitions, factory, resolver, xsdTypesMap);
        return definitions;
    }

}
