/*
 * 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.policy.xml;

import static javax.xml.stream.XMLStreamConstants.END_ELEMENT;
import static javax.xml.stream.XMLStreamConstants.START_ELEMENT;

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

import javax.xml.namespace.QName;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamReader;
import javax.xml.stream.XMLStreamWriter;

import org.apache.tuscany.sca.contribution.processor.BaseStAXArtifactProcessor;
import org.apache.tuscany.sca.contribution.processor.ContributionReadException;
import org.apache.tuscany.sca.contribution.processor.ContributionResolveException;
import org.apache.tuscany.sca.contribution.processor.ContributionWriteException;
import org.apache.tuscany.sca.contribution.processor.ProcessorContext;
import org.apache.tuscany.sca.contribution.processor.StAXArtifactProcessor;
import org.apache.tuscany.sca.contribution.resolver.ModelResolver;
import org.apache.tuscany.sca.core.FactoryExtensionPoint;
import org.apache.tuscany.sca.monitor.Monitor;
import org.apache.tuscany.sca.monitor.Problem;
import org.apache.tuscany.sca.monitor.Problem.Severity;
import org.apache.tuscany.sca.policy.ExtensionType;
import org.apache.tuscany.sca.policy.Intent;
import org.apache.tuscany.sca.policy.PolicyFactory;
import org.apache.tuscany.sca.policy.Intent.Type;

/**
 * Processor for handling XML models of PolicyIntent definitions
 *
 * @version $Rev$ $Date$
 */
public class IntentProcessor extends BaseStAXArtifactProcessor implements StAXArtifactProcessor<Intent>,
    PolicyConstants {

    private PolicyFactory policyFactory;
    

    public IntentProcessor(FactoryExtensionPoint modelFactories) {
        this.policyFactory = modelFactories.getFactory(PolicyFactory.class);
    }

    public IntentProcessor(PolicyFactory policyFactory) {
        this.policyFactory = policyFactory;
    }

    /**
     * Report a error.
     * 
     * @param problems
     * @param message
     * @param model
     */
    private void error(Monitor monitor, String message, Object model, Object... messageParameters) {
        if (monitor != null) {
            Problem problem =
                monitor.createProblem(this.getClass().getName(),
                                      Messages.RESOURCE_BUNDLE,
                                      Severity.ERROR,
                                      model,
                                      message,
                                      messageParameters);
            monitor.problem(problem);
        }
    }

    private void warn(Monitor monitor, String message, Object model, Object... messageParameters) {
        if (monitor != null) {
            Problem problem =
                monitor.createProblem(this.getClass().getName(),
                                      Messages.RESOURCE_BUNDLE,
                                      Severity.WARNING,
                                      model,
                                      message,
                                      messageParameters);
            monitor.problem(problem);
        }
    }

    public Intent read(XMLStreamReader reader, ProcessorContext context) throws ContributionReadException, XMLStreamException {
        Intent intent = null;
        String intentLocalName = reader.getAttributeValue(null, NAME);
        if (intentLocalName == null) {
            error(context.getMonitor(), "IntentNameMissing", reader);
            return null;
        }

        String intentType = reader.getAttributeValue(null, INTENT_TYPE);
        if (intentType == null) {
            intentType = Intent.Type.interaction.name();
        }

        intent = policyFactory.createIntent();

        // [rfeng] the target namespace is not available, set the local part for now
        // This will be changed in the definitions processor
        intent.setName(new QName(intentLocalName));
        intent.setType(Type.valueOf(intentType));

        readRequiredIntents(intent, reader, context);
        readExcludedIntents(intent, reader);

        readConstrainedTypes(intent, reader);
        
        String mutuallyExclusiveString = reader.getAttributeValue(null, MUTUALLY_EXCLUSIVE);
        if (mutuallyExclusiveString != null &&
            mutuallyExclusiveString.equals("true")){
            intent.setMutuallyExclusive(true);
        } else {
            intent.setMutuallyExclusive(false);
        }

        Intent current = intent;
        int event = reader.getEventType();
        QName name = null;
        while (reader.hasNext()) {
            event = reader.getEventType();
            switch (event) {
                case START_ELEMENT: {
                    name = reader.getName();
                    if (DESCRIPTION_QNAME.equals(name)) {
                        String text = reader.getElementText();
                        if (text != null) {
                            text = text.trim();
                        }
                        current.setDescription(text);
                    } else if (INTENT_QUALIFIER_QNAME.equals(name)) {
                        String qualifierName = reader.getAttributeValue(null, NAME);
                        String defaultQ = reader.getAttributeValue(null, DEFAULT);
                        boolean isDefault = defaultQ == null ? false : Boolean.parseBoolean(defaultQ);
                        String qualifiedIntentName = intentLocalName + QUALIFIER + qualifierName;
                        Intent qualified = policyFactory.createIntent();
                        qualified.setUnresolved(false);
                        qualified.setType(intent.getType());
                        qualified.setName(new QName(qualifiedIntentName));
                        if (isDefault) {
                            if (intent.getDefaultQualifiedIntent() == null){
                                intent.setDefaultQualifiedIntent(qualified);
                            } else {
                                Monitor.error(context.getMonitor(), 
                                              this, 
                                              Messages.RESOURCE_BUNDLE, 
                                              "MultipleDefaultQualifiers", 
                                              intent.getName().toString());
                            }
                        }
                        
                        // check that the qualifier is unique
                        if ( !intent.getQualifiedIntents().contains(qualified)){
                            intent.getQualifiedIntents().add(qualified);
                        } else {
                            Monitor.error(context.getMonitor(), 
                                          this, 
                                          Messages.RESOURCE_BUNDLE, 
                                          "QualifierIsNotUnique", 
                                          intent.getName().toString(),
                                          qualifierName);
                        }
                        
                        qualified.setQualifiableIntent(intent);
                        current = qualified;
                    }
                    break;
                }
                case END_ELEMENT: {
                    name = reader.getName();
                    if (INTENT_QUALIFIER_QNAME.equals(name)) {
                        current = intent;
                    }
                    break;
                }
            }
            if (event == END_ELEMENT && POLICY_INTENT_QNAME.equals(reader.getName())) {
                break;
            }

            //Read the next element
            if (reader.hasNext()) {
                reader.next();
            }
        }
        // REVIEW: [rfeng] What's going to happen if there is only one qualified intent
        if (intent.getQualifiedIntents().size() == 1) {
            intent.setDefaultQualifiedIntent(intent.getQualifiedIntents().get(0));
        }
        
        // set all qualified intents as excluding one another if the qualifiable
        // intent is set to be mutually exclusive
        if (intent.isMutuallyExclusive()){
            for (Intent qualifiedIntent : intent.getQualifiedIntents()){
                for (Intent excludedIntent : intent.getQualifiedIntents()){
                    if (qualifiedIntent != excludedIntent){
                        qualifiedIntent.getExcludedIntents().add(excludedIntent);
                   }
                }
            }
        }
        
        return intent;
    }

    public void write(Intent intent, XMLStreamWriter writer, ProcessorContext context) throws ContributionWriteException, XMLStreamException {
        // Write an <sca:intent>
        writer.writeStartElement(PolicyConstants.SCA11_NS, INTENT);
        writer.writeNamespace(intent.getName().getPrefix(), intent.getName().getNamespaceURI());
        writer.writeAttribute(PolicyConstants.NAME, intent.getName().getPrefix() + COLON
            + intent.getName().getLocalPart());
        if (intent.getRequiredIntents() != null && intent.getRequiredIntents().size() > 0) {
            StringBuffer sb = new StringBuffer();
            for (Intent requiredIntents : intent.getRequiredIntents()) {
                sb.append(requiredIntents.getName());
                sb.append(" ");
            }
            writer.writeAttribute(PolicyConstants.REQUIRES, sb.toString());
        }

        if (intent.getExcludedIntents() != null && intent.getExcludedIntents().size() > 0) {
            StringBuffer sb = new StringBuffer();
            for (Intent excludedIntents : intent.getExcludedIntents()) {
                sb.append(excludedIntents.getName());
                sb.append(" ");
            }
            writer.writeAttribute(PolicyConstants.EXCLUDES, sb.toString());
        }

        if (intent.getConstrainedTypes() != null && intent.getConstrainedTypes().size() > 0) {
            StringBuffer sb = new StringBuffer();
            for (ExtensionType contrainedArtifact : intent.getConstrainedTypes()) {
                sb.append(contrainedArtifact.getType().getPrefix());
                sb.append(':').append(contrainedArtifact.getType().getLocalPart());
                sb.append(" ");
            }
            writer.writeAttribute(CONSTRAINS, sb.toString());
        }

        if (intent.getDescription() != null && intent.getDescription().length() > 0) {
            writer.writeStartElement(PolicyConstants.SCA11_NS, DESCRIPTION);
            writer.writeCData(intent.getDescription());
            writer.writeEndElement();
        }

        writer.writeEndElement();
    }

    private void resolveContrainedTypes(Intent intent, ModelResolver resolver, ProcessorContext context) throws ContributionResolveException {
        Collection<ExtensionType> resolvedTypes = new HashSet<ExtensionType>();
        for (ExtensionType extensionType : intent.getConstrainedTypes()) {
            if (ExtensionType.BINDING_BASE.equals(extensionType.getType()) || ExtensionType.IMPLEMENTATION_BASE
                .equals(extensionType.getType())) {
                // HACK: Mark sca:binding and sca:implementation as resolved
                extensionType.setUnresolved(false);
                resolvedTypes.add(extensionType);
            } else {
                ExtensionType resolved = resolver.resolveModel(ExtensionType.class, extensionType, context);
                if (!resolved.isUnresolved() || resolved != extensionType) {
                    resolvedTypes.add(resolved);
                } else {
                    warn(context.getMonitor(), "ConstrainedTypeNotFound", intent, extensionType, intent);
                }
            }
        }
        intent.getConstrainedTypes().clear();
        intent.getConstrainedTypes().addAll(resolvedTypes);
    }

    private void resolveProfileIntent(Intent intent, ModelResolver resolver, ProcessorContext context) throws ContributionResolveException {
        Monitor monitor = context.getMonitor();
        // FIXME: Need to check for cyclic references first i.e an A requiring B
        // and then B requiring A...
        if (intent != null && !intent.getRequiredIntents().isEmpty()) {
            // resolve all required intents
            List<Intent> requiredIntents = new ArrayList<Intent>();
            for (Intent required : intent.getRequiredIntents()) {
                if (required.isUnresolved()) {
                    Intent resolved = resolver.resolveModel(Intent.class, required, context);
                    // At this point, when the required intent is not resolved, it does not mean 
                    // its undeclared, chances are that their dependency are not resolved yet. 
                    // Lets try to resolve them first.
                    if (resolved.isUnresolved()) {
                        if (((resolved).getRequiredIntents()).contains(intent)) {
                            error(monitor, "CyclicReferenceFound", resolver, required, intent);
                            return;
                        }
                    }

                    if (!resolved.isUnresolved() || resolved != required) {
                        requiredIntents.add(resolved);
                    } else {
                        error(monitor, "RequiredIntentNotFound", resolver, required, intent);
                        return;
                        //throw new ContributionResolveException("Required Intent - " + requiredIntent
                        //+ " not found for Intent " + policyIntent);
                    }
                } else {
                    requiredIntents.add(required);
                }
            }
            intent.getRequiredIntents().clear();
            intent.getRequiredIntents().addAll(requiredIntents);
        }
    }

    private void resolveQualifiedIntent(Intent qualifed, ModelResolver resolver, ProcessorContext context) throws ContributionResolveException {
        if (qualifed != null) {
            //resolve the qualifiable intent
            Intent parent = qualifed.getQualifiableIntent();
            if (parent == null) {
                return;
            }
            if (parent.isUnresolved()) {
                Intent resolved = resolver.resolveModel(Intent.class, parent, context);
                // At this point, when the qualifiable intent is not resolved, it does not mean 
                // its undeclared, chances are that their dependency are not resolved yet. 
                // Lets try to resolve them first.

                if (!resolved.isUnresolved() || resolved != qualifed) {
                    qualifed.setQualifiableIntent(resolved);
                } else {
                    error(context.getMonitor(), "QualifiableIntentNotFound", resolver, parent, qualifed);
                    //throw new ContributionResolveException("Qualifiable Intent - " + qualifiableIntent
                    //+ " not found for Intent " + policyIntent);
                }
            }
        }
    }

    public void resolve(Intent intent, ModelResolver resolver, ProcessorContext context) throws ContributionResolveException {
        if (intent != null && intent.isUnresolved()) {
            resolveProfileIntent(intent, resolver, context);
            resolveExcludedIntents(intent, resolver, context);
            resolveQualifiedIntent(intent, resolver, context);
            resolveContrainedTypes(intent, resolver, context);
            intent.setUnresolved(false);
        }
    }

    public QName getArtifactType() {
        return POLICY_INTENT_QNAME;
    }

    private void readConstrainedTypes(Intent policyIntent, XMLStreamReader reader) throws ContributionReadException {
        String value = reader.getAttributeValue(null, CONSTRAINS);
        if (value != null) {
            List<ExtensionType> constrainedTypes = policyIntent.getConstrainedTypes();
            for (StringTokenizer tokens = new StringTokenizer(value); tokens.hasMoreTokens();) {
                QName qname = getQNameValue(reader, tokens.nextToken());
                ExtensionType extensionType = policyFactory.createExtensionType();
                extensionType.setType(qname);
                constrainedTypes.add(extensionType);
            }
        }
    }

    private void readRequiredIntents(Intent intent, XMLStreamReader reader, ProcessorContext context) {
        String value = reader.getAttributeValue(null, REQUIRES);
        if (value != null) {
            List<Intent> requiredIntents = intent.getRequiredIntents();
            for (StringTokenizer tokens = new StringTokenizer(value); tokens.hasMoreTokens();) {
                QName qname = getQNameValue(reader, tokens.nextToken());
                Intent required = policyFactory.createIntent();
                required.setName(qname);
                required.setUnresolved(true);
                requiredIntents.add(required);
            }
            
            // Check that a profile intent does not have "." in its name 
            if (requiredIntents.size() > 0) {
                if (intent.getName().getLocalPart().contains(".")){
                    Monitor.error(context.getMonitor(), 
                                  this, 
                                  Messages.RESOURCE_BUNDLE, 
                                  "ProfileIntentNameWithPeriod", 
                                  intent.getName().toString());
                }
            }
        }
    }

    private void readExcludedIntents(Intent intent, XMLStreamReader reader) {
        String value = reader.getAttributeValue(null, EXCLUDES);
        if (value != null) {
            List<Intent> excludedIntents = intent.getExcludedIntents();
            for (StringTokenizer tokens = new StringTokenizer(value); tokens.hasMoreTokens();) {
                QName qname = getQNameValue(reader, tokens.nextToken());
                Intent excluded = policyFactory.createIntent();
                excluded.setName(qname);
                excluded.setUnresolved(true);
                excludedIntents.add(excluded);
            }
        }
    }

    private void resolveExcludedIntents(Intent policyIntent, ModelResolver resolver, ProcessorContext context)
        throws ContributionResolveException {
        if (policyIntent != null) {
            // resolve all excluded intents
            List<Intent> excludedIntents = new ArrayList<Intent>();
            for (Intent excludedIntent : policyIntent.getExcludedIntents()) {
                if (excludedIntent.isUnresolved()) {
                    Intent resolvedExcludedIntent = resolver.resolveModel(Intent.class, excludedIntent, context);
                    if (!resolvedExcludedIntent.isUnresolved() || resolvedExcludedIntent != excludedIntent) {
                        excludedIntents.add(resolvedExcludedIntent);
                    } else {
                        error(context.getMonitor(), "ExcludedIntentNotFound", resolver, excludedIntent, policyIntent);
                        return;
                        //throw new ContributionResolveException("Excluded Intent " + excludedIntent
                        //+ " not found for intent " + policyIntent);
                    }
                } else {
                    excludedIntents.add(excludedIntent);
                }
            }
            policyIntent.getExcludedIntents().clear();
            policyIntent.getExcludedIntents().addAll(excludedIntents);
        }
    }

    public Class<Intent> getModelType() {
        return Intent.class;
    }

}
