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

import java.util.Map;
import java.util.Map.Entry;

/**
 * TODO support namespaces (inherited from outer/inheriting for inner elements)
 *
 * @author The Apache MINA Project (dev@mina.apache.org)
 */
public class Renderer {

    private XMLElement topElement;
    private StringBuilder openElementBuffer = new StringBuilder();
    private StringBuilder elementContentBuffer = new StringBuilder();
    private StringBuilder closeElementBuffer = new StringBuilder();
    private static final String COLON = ":";

    public Renderer(XMLElement element) {
        this.topElement = element;
        
        StackNamespaceResolver nsResolver = new StackNamespaceResolver();
        renderXMLElement(topElement, nsResolver, openElementBuffer, elementContentBuffer, closeElementBuffer);
    }

    public String getOpeningElement() {
        return openElementBuffer.toString();
    }

    public String getElementContent() {
        return elementContentBuffer.toString();
    }

    public String getClosingElement() {
        return closeElementBuffer.toString();
    }

    public String getComplete() {
        return openElementBuffer.toString() + elementContentBuffer.toString() + closeElementBuffer.toString();
    }

    private void renderXMLElement(XMLElement element, StackNamespaceResolver nsResolver, StringBuilder openElementBuffer, StringBuilder elementContentBuffer, StringBuilder closeElementBuffer) {
        nsResolver.push(element);
    	
    	openElementBuffer.append("<");
        renderElementName(openElementBuffer, element, nsResolver);
        
        // render namespace delcarations
        Map<String, String> nsAttrs = nsResolver.getNamespaceDeclarations();
        for(Entry<String, String> nsAttr : nsAttrs.entrySet()) {
    		openElementBuffer.append(" ");
    		String name;
            String value = nsAttr.getValue();
    		if(value == null || value.length() == 0) {
                continue; // don't issue "xmlns=''", this will only confuse clients
            } else if(nsAttr.getKey().length() == 0) {
    			name = "xmlns";
    		} else {
    			name = "xmlns:" + nsAttr.getKey();
    		}
            renderAttribute(openElementBuffer, name, value);
        }
        
        for (Attribute attribute : element.getAttributes()) {
        	// make sure we do not render namespace attributes, 
        	// nor normal attributes containing namespace declarations (probably due to
        	// the parser not correctly creating namespace attributes for these which are then 
        	// copied into for example error responses)
        	if(!(attribute instanceof NamespaceAttribute) && !hasXmlnsReservedName(attribute)) {
        		openElementBuffer.append(" ");
        		renderAttribute(openElementBuffer, attribute, nsResolver);
        	}
        }
        openElementBuffer.append(">");

        for (XMLFragment xmlFragment : element.getInnerFragments()) {
            if (xmlFragment instanceof XMLElement) renderXMLElement((XMLElement) xmlFragment, nsResolver, elementContentBuffer, elementContentBuffer, elementContentBuffer);
            else if (xmlFragment instanceof XMLText) {
                elementContentBuffer.append(escapeTextValue(((XMLText) xmlFragment).getText()));
            } else {
                throw new UnsupportedOperationException("cannot render XML fragment of type " + xmlFragment.getClass().getName());
            }
        }

        closeElementBuffer.append("</");
        renderElementName(closeElementBuffer, element, nsResolver);
        closeElementBuffer.append(">");
        
        // remove this element from the NS resolver stack
        nsResolver.pop();
    }

    private boolean hasXmlnsReservedName(Attribute attribute) {
    	String name = attribute.getName();
    	return name.equals("xmlns") || name.startsWith("xmlns:");
    }
    
    private void renderElementName(StringBuilder buffer, XMLElement element, NamespaceResolver nsResolver) {
        // if the element has a namespace prefix, retrieves the prefix from the defining attribute
        if (element.getNamespacePrefix().length() > 0) {
            buffer.append(element.getNamespacePrefix()).append(COLON);
        } else if(element.getNamespaceURI().length() > 0) {
        	// element is in a namespace, but without a declared prefix, we need to resolve the prefix
        	String prefix = nsResolver.resolvePrefix(element.getNamespaceURI());
        	if(prefix != null && prefix.length() > 0) {
        		buffer.append(prefix).append(COLON);
        	}
        }

        buffer.append(element.getName());
    }

    private void renderAttribute(StringBuilder buffer, Attribute attribute, NamespaceResolver nsResolver) {
    	String qname;
    	if(!attribute.getNamespaceUri().equals("")) {
    		// attribute is in a namespace, resolve prefix
    		qname = nsResolver.resolvePrefix(attribute.getNamespaceUri()) + ":" + attribute.getName();
    	} else {
    		qname = attribute.getName();
    	}
    	
    	renderAttribute(buffer, qname, attribute.getValue());
    }
    
    private void renderAttribute(StringBuilder buffer, String qname, String value) {
        buffer.append(qname).append("=\"").append(escapeAttributeValue(value)).append("\"");
    }
    
    private String escapeAttributeValue(String value) {
    	return value.replace("&", "&amp;").replace("\"", "&quot;").replace("<", "&lt;").replace(">", "&gt;");
    }

    private String escapeTextValue(String value) {
    	return value.replace("&", "&amp;").replace("<", "&lt;").replace(">", "&gt;");
    }

}
