/*
 *  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.vysper.xmpp.stanza;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.apache.vysper.xml.fragment.AbstractXMLElementBuilder;
import org.apache.vysper.xml.fragment.Attribute;
import org.apache.vysper.xml.fragment.XMLElement;
import org.apache.vysper.xml.fragment.XMLFragment;
import org.apache.vysper.xml.fragment.XMLText;
import org.apache.vysper.xmpp.addressing.Entity;
import org.apache.vysper.xmpp.addressing.EntityImpl;
import org.apache.vysper.xmpp.protocol.NamespaceURIs;
import org.apache.vysper.xmpp.protocol.commandstanza.EndOfSessionCommandStanza;
import org.apache.vysper.xmpp.server.SessionContext;

/**
 *
 * @author The Apache MINA Project (dev@mina.apache.org)
 */
public class StanzaBuilder extends AbstractXMLElementBuilder<StanzaBuilder, Stanza> {

    public static StanzaBuilder createIQStanza(Entity from, Entity to, IQStanzaType type, String id) {
        StanzaBuilder stanzaBuilder = new StanzaBuilder("iq", NamespaceURIs.JABBER_CLIENT);
        if (from != null)
            stanzaBuilder.addAttribute("from", from.getFullQualifiedName());
        if (to != null)
            stanzaBuilder.addAttribute("to", to.getFullQualifiedName());
        stanzaBuilder.addAttribute("type", type.value());
        stanzaBuilder.addAttribute("id", id);
        return stanzaBuilder;
    }

    public static StanzaBuilder createMessageStanza(Entity from, Entity to, String lang, String body) {
        StanzaBuilder stanzaBuilder = new StanzaBuilder("message", NamespaceURIs.JABBER_CLIENT);
        stanzaBuilder.addAttribute("from", from.getFullQualifiedName());
        stanzaBuilder.addAttribute("to", to.getFullQualifiedName());
        if (lang != null)
            stanzaBuilder.addAttribute(NamespaceURIs.XML, "lang", lang);
        if (body != null)
            stanzaBuilder.startInnerElement("body", NamespaceURIs.JABBER_CLIENT).addText(body).endInnerElement();
        return stanzaBuilder;
    }

    public static StanzaBuilder createMessageStanza(Entity from, Entity to, MessageStanzaType type, String lang,
            String body) {
        StanzaBuilder stanzaBuilder = createMessageStanza(from, to, lang, body);
        if (type != null)
            stanzaBuilder.addAttribute("type", type.value());
        return stanzaBuilder;
    }

    public static Stanza createUnavailablePresenceStanza(String status,
            SessionContext.SessionTerminationCause terminationCause) {
        StanzaBuilder presenceUnavailBuilder = createPresenceStanza(null, null, null, PresenceStanzaType.UNAVAILABLE,
                null, status);
        if (terminationCause == null) {
            return presenceUnavailBuilder.build();
        } else {
            return new EndOfSessionCommandStanza(presenceUnavailBuilder.build(), terminationCause);
        }
    }

    public static StanzaBuilder createPresenceStanza(Entity from, Entity to, String lang, PresenceStanzaType type,
            String show, String status) {
        StanzaBuilder stanzaBuilder = new StanzaBuilder("presence", NamespaceURIs.JABBER_CLIENT);
        if (from != null)
            stanzaBuilder.addAttribute("from", from.getFullQualifiedName());
        if (to != null)
            stanzaBuilder.addAttribute("to", to.getFullQualifiedName());
        if (lang != null)
            stanzaBuilder.addAttribute(NamespaceURIs.XML, "lang", lang);
        if (type != null)
            stanzaBuilder.addAttribute("type", type.value());
        if (show != null) {
            stanzaBuilder.startInnerElement("show", NamespaceURIs.JABBER_CLIENT).addText(show).endInnerElement();
        }
        if (status != null) {
            stanzaBuilder.startInnerElement("status", NamespaceURIs.JABBER_CLIENT).addText(status).endInnerElement();
        }
        return stanzaBuilder;
    }

    public static StanzaBuilder createDirectReply(XMPPCoreStanza original, boolean fromIsServerOnly, IQStanzaType type) {
        return createDirectReply(original, fromIsServerOnly, type == null ? null : type.value());
    }

    public static StanzaBuilder createDirectReply(XMPPCoreStanza original, boolean fromIsServerOnly, String type) {
        if (original == null)
            throw new IllegalArgumentException();

        StanzaBuilder stanzaBuilder = new StanzaBuilder(original.getName(), original.getNamespaceURI(), original
                .getNamespacePrefix());
        // reverse to and from
        Entity newTo = original.getFrom();
        if (newTo != null) {
            stanzaBuilder.addAttribute("to", newTo.getFullQualifiedName());
        }
        Entity newFrom = original.getTo();
        if (newFrom != null) {
            if (fromIsServerOnly)
                newFrom = new EntityImpl(null, newFrom.getDomain(), null);
            stanzaBuilder.addAttribute("from", newFrom.getFullQualifiedName());
        }
        stanzaBuilder.addAttribute("type", type);
        if (original.getID() != null)
            stanzaBuilder.addAttribute("id", original.getID());

        return stanzaBuilder;
    }

    /**
     * creates a clone of the given original stanza into the returned StanzaBuilder, but replaces all attributes in the
     * top-level original element with the values from the given attribute list.
     * this way, the builder can be coerced into the final stanza (calling StanzaBuilder#getFinalStanza() or be used to
     * add additional attributes and inner elements.
     * @param original
     * @param replacingAttributes - if this is a short list, iteration is more efficient than hash mapping
     * @param deep
     * @return
     */
    public static StanzaBuilder createClone(XMLElement original, boolean deep, List<Attribute> replacingAttributes) {
        StanzaBuilder stanzaBuilder = new StanzaBuilder(original.getName(), original.getNamespaceURI(), original
                .getNamespacePrefix());

        List<Attribute> replacingAttributesCopy = new ArrayList<Attribute>();
        if (replacingAttributes != null)
            replacingAttributesCopy.addAll(replacingAttributes);

        List<Attribute> originalAttributes = original.getAttributes();
        for (Attribute originalAttribute : originalAttributes) {
            boolean wasReplaced = false;
            for (Iterator<Attribute> it = replacingAttributesCopy.iterator(); it.hasNext();) {
                Attribute replacingAttribute = it.next();
                if (replacingAttribute == null)
                    continue;
                if (replacingAttribute.getName().equals(originalAttribute.getName())) {
                    stanzaBuilder.addAttribute(replacingAttribute);
                    it.remove(); // this has been processed
                    wasReplaced = true;
                    break;
                }
            }
            if (!wasReplaced)
                stanzaBuilder.addAttribute(originalAttribute);
        }

        // add remaining replacements, which are actually additions
        for (Attribute additionalAttribute : replacingAttributesCopy) {
            stanzaBuilder.addAttribute(additionalAttribute);
        }

        // copy over immutable inner elements
        if (deep && original.getInnerElements() != null) {
            List<XMLElement> innerElements = original.getInnerElements();
            for (XMLElement innerElement : innerElements) {
                stanzaBuilder.addPreparedElement(innerElement);
            }
        }

        return stanzaBuilder;
    }

    /**
     * creates a new stanza which only differs from the given original by 'from' and 'to' attributes. 
     * 
     * @param original 
     * @param from if NOT NULL, the new 'from'
     * @param to if NOT NULL, the new 'to'
     * @return stanza builder with to and from replaced
     */
    public static StanzaBuilder createForward(Stanza original, Entity from, Entity to) {
        List<Attribute> toFromReplacements = new ArrayList<Attribute>(2);
        if (to != null)
            toFromReplacements.add(new Attribute("to", to.getFullQualifiedName()));
        if (from != null)
            toFromReplacements.add(new Attribute("from", from.getFullQualifiedName()));

        return createClone(original, true, toFromReplacements);
    }

    /**
     * convenience shortcut for {@link #createForward(Stanza, org.apache.vysper.xmpp.addressing.Entity, org.apache.vysper.xmpp.addressing.Entity)}
     * 
     * @param original 
     * @param from if NOT NULL, the new 'from'
     * @param to if NOT NULL, the new 'to'
     * @return forward stanza
     */
    public static Stanza createForwardStanza(Stanza original, Entity from, Entity to) {
        return createForward(original, from, to).build();
    }
    
    public static Stanza rewriteNamespace(Stanza stanza, String fromNamespaceUri, String toNamespaceUri) {
        StanzaBuilder builder = new StanzaBuilder(stanza.getName(), toNamespaceUri, stanza.getNamespacePrefix());
        for(Attribute attribute : stanza.getAttributes()) {
            builder.addAttribute(attribute);
        }
        
        for(XMLFragment fragment : stanza.getInnerFragments()) {
            if(fragment instanceof XMLElement) {
                rewriteNamespace((XMLElement) fragment, builder, fromNamespaceUri, toNamespaceUri);
            } else {
                // XMLText
                builder.addText(((XMLText)fragment).getText());
            }
        }
        
        return builder.build();
    }
    
    private static void rewriteNamespace(XMLElement element, StanzaBuilder builder, String fromNamespaceUri, String toNamespaceUri) {
        if(fromNamespaceUri.equals(element.getNamespaceURI())) {
            builder.startInnerElement(element.getName(), toNamespaceUri);
            for(Attribute attribute : element.getAttributes()) {
                builder.addAttribute(attribute);
            }
            for(XMLFragment fragment : element.getInnerFragments()) {
                if(fragment instanceof XMLElement) {
                    rewriteNamespace((XMLElement) fragment, builder, fromNamespaceUri, toNamespaceUri);
                } else {
                    // XMLText
                    builder.addText(((XMLText)fragment).getText());
                }
            }
            builder.endInnerElement();
        } else {
            builder.addPreparedElement(element);
        }
    }

    static class ElementStruct {
        public ElementStruct parentElement = null;

        public XMLElement element = null;

        public List<Attribute> attributes = null;

        public List<XMLFragment> innerFragments = null;
    }

    public StanzaBuilder(String stanzaName) {
        this(stanzaName, null);
    }

    public StanzaBuilder(String stanzaName, String namespaceURI) {
        this(stanzaName, namespaceURI, null);
    }

    public StanzaBuilder(String stanzaName, String namespaceURI, String namespacePrefix) {
        super(stanzaName, namespaceURI, namespacePrefix);
    }

    public StanzaBuilder(String stanzaName, String namespaceURI, String namespacePrefix, List<Attribute> attributes,
            List<XMLFragment> innerFragments) {
        super(stanzaName, namespaceURI, namespacePrefix, attributes, null, innerFragments);
    }

    public StanzaBuilder(String stanzaName, String namespaceURI, String namespacePrefix, List<Attribute> attributes,
            Map<String, String> namespaces, List<XMLFragment> innerFragments) {
        super(stanzaName, namespaceURI, namespacePrefix, attributes, namespaces, innerFragments);
    }

    protected XMLElement createElement(String namespaceURI, String name, String namespacePrefix,
            List<Attribute> attributes, Map<String, String> namespaces, List<XMLFragment> innerFragments) {
        // when creating the first element, make it a stanza
        if (currentElement == null) {
            return new Stanza(namespaceURI, name, namespacePrefix, attributes, innerFragments, namespaces);
        } else {
            return new XMLElement(namespaceURI, name, namespacePrefix, attributes, innerFragments, namespaces);
        }
    }
}
