/*
 * 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.axis2.json.gson;

import com.google.gson.stream.JsonWriter;
import org.apache.axis2.context.ConfigurationContext;
import org.apache.axis2.json.factory.JSONType;
import org.apache.axis2.json.factory.JsonConstant;
import org.apache.axis2.json.factory.JsonObject;
import org.apache.axis2.json.factory.XmlNode;
import org.apache.axis2.json.factory.XmlNodeGenerator;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.ws.commons.schema.XmlSchema;

import javax.xml.namespace.NamespaceContext;
import javax.xml.namespace.QName;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamWriter;
import java.io.IOException;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Queue;
import java.util.Stack;


public class GsonXMLStreamWriter implements XMLStreamWriter {

    private static final Log log = LogFactory.getLog(GsonXMLStreamWriter.class);

    private JsonWriter jsonWriter;

    /**
     * queue is used to keep the outgoing response structure according to the response XMLSchema
     */
    private Queue<JsonObject> queue = new LinkedList<JsonObject>();

    /**
     * This stacks use to process the outgoing response
     */
    private Stack<JsonObject> stack = new Stack<JsonObject>();
    private Stack<JsonObject> miniStack = new Stack<JsonObject>();

    private JsonObject flushObject;

    /**
     * topNestedArrayObj is use to keep the most top nested array object
     */
    private JsonObject topNestedArrayObj;

    /**
     * processedJsonObject stack is used to keep processed JsonObject for future reference
     */
    private Stack<JsonObject> processedJsonObjects = new Stack<JsonObject>();

    private List<XmlSchema> xmlSchemaList;

    /**
     * Element QName of outgoing message , which is get from the outgoing message context
     */
    private QName elementQName;

    /**
     * Intermediate representation of XmlSchema
     */
    private XmlNode mainXmlNode;

    private ConfigurationContext configContext;

    private XmlNodeGenerator xmlNodeGenerator;

    private boolean isProcessed;

    /**
     * This map is used to keep namespace uri with prefixes
     */
    private Map<String, String> uriPrefixMap = new HashMap<String, String>();


    public GsonXMLStreamWriter(JsonWriter jsonWriter, QName elementQName, List<XmlSchema> xmlSchemaList,
                               ConfigurationContext context) {
        this.jsonWriter = jsonWriter;
        this.elementQName = elementQName;
        this.xmlSchemaList = xmlSchemaList;
        this.configContext = context;
    }

    private void process() throws IOException {
        Object ob = configContext.getProperty(JsonConstant.XMLNODES);
        if (ob != null) {
            Map<QName, XmlNode> nodeMap = (Map<QName, XmlNode>) ob;
            XmlNode resNode = nodeMap.get(elementQName);
            if (resNode != null) {
                xmlNodeGenerator = new XmlNodeGenerator();
                queue = xmlNodeGenerator.getQueue(resNode);
            } else {
                xmlNodeGenerator = new XmlNodeGenerator(xmlSchemaList, elementQName);
                mainXmlNode = xmlNodeGenerator.getMainXmlNode();
                queue = xmlNodeGenerator.getQueue(mainXmlNode);
                nodeMap.put(elementQName, mainXmlNode);
                configContext.setProperty(JsonConstant.XMLNODES, nodeMap);
            }
        } else {
            Map<QName, XmlNode> newNodeMap = new HashMap<QName, XmlNode>();
            xmlNodeGenerator = new XmlNodeGenerator(xmlSchemaList, elementQName);
            mainXmlNode = xmlNodeGenerator.getMainXmlNode();
            queue = xmlNodeGenerator.getQueue(mainXmlNode);
            newNodeMap.put(elementQName, mainXmlNode);
            configContext.setProperty(JsonConstant.XMLNODES, newNodeMap);
        }
        isProcessed = true;
        this.jsonWriter.beginObject();
        log.debug("GsonXMLStreamWriter.process() completed");
    }


    private void writeStartJson(JsonObject jsonObject) throws IOException {

        if (jsonObject.getType() == JSONType.OBJECT) {
            jsonWriter.name(jsonObject.getName());
        } else if (jsonObject.getType() == JSONType.ARRAY) {
            jsonWriter.name(jsonObject.getName());
            jsonWriter.beginArray();

        } else if (jsonObject.getType() == JSONType.NESTED_ARRAY) {
            jsonWriter.name(jsonObject.getName());
            jsonWriter.beginArray();
            jsonWriter.beginObject();
            if (topNestedArrayObj == null) {
                topNestedArrayObj = jsonObject;
                processedJsonObjects.push(jsonObject);
            }
        } else if (jsonObject.getType() == JSONType.NESTED_OBJECT) {
            jsonWriter.name(jsonObject.getName());
            jsonWriter.beginObject();

        }

    }

    private void writeEndJson(JsonObject endJson) throws IOException {
        if (endJson.getType() == JSONType.OBJECT) {
            // nothing write to json writer
        } else if (endJson.getType() == JSONType.ARRAY) {
            jsonWriter.endArray();
        } else if (endJson.getType() == JSONType.NESTED_ARRAY) {
            jsonWriter.endArray();
        } else if (endJson.getType() == JSONType.NESTED_OBJECT) {
            jsonWriter.endObject();
        }

    }


    private JsonObject popStack() {
        if (topNestedArrayObj == null || stack.peek().getType() == JSONType.NESTED_OBJECT
                || stack.peek().getType() == JSONType.NESTED_ARRAY) {
            return stack.pop();
        } else {
            processedJsonObjects.push(stack.peek());
            return stack.pop();
        }
    }

    private void fillMiniStack(JsonObject nestedJsonObject) {

        while (!processedJsonObjects.peek().getName().equals(nestedJsonObject.getName())) {
            miniStack.push(processedJsonObjects.pop());
        }
        processedJsonObjects.pop();
    }


    /**
     * Writes a start tag to the output.  All writeStartElement methods
     * open a new scope in the internal namespace context.  Writing the
     * corresponding EndElement causes the scope to be closed.
     *
     * @param localName local name of the tag, may not be null
     * @throws javax.xml.stream.XMLStreamException
     *
     */

    public void writeStartElement(String localName) throws XMLStreamException {
        if (!isProcessed) {
            try {
                process();
            } catch (IOException e) {
                throw new XMLStreamException("Error occours while write first begin object ");
            }
        }
        JsonObject stackObj = null;
        try {
            if (miniStack.isEmpty()) {
                if (!queue.isEmpty()) {
                    JsonObject queObj = queue.peek();
                    if (queObj.getName().equals(localName)) {
                        if (flushObject != null) {
                            if (topNestedArrayObj != null && flushObject.getType() == JSONType.NESTED_ARRAY
                                    && flushObject.getName().equals(topNestedArrayObj.getName())) {
                                topNestedArrayObj = null;
                                processedJsonObjects.clear();
                            }
                            popStack();
                            writeEndJson(flushObject);
                            flushObject = null;
                        }

                        if (topNestedArrayObj != null && (queObj.getType() == JSONType.NESTED_ARRAY ||
                                queObj.getType() == JSONType.NESTED_OBJECT)) {
                            processedJsonObjects.push(queObj);
                        }
                        writeStartJson(queObj);
                        stack.push(queue.poll());
                    } else if (!stack.isEmpty()) {
                        stackObj = stack.peek();
                        if (stackObj.getName().equals(localName)) {
                            if (stackObj.getType() == JSONType.NESTED_ARRAY) {
                                fillMiniStack(stackObj);
                                jsonWriter.beginObject();
                                processedJsonObjects.push(stackObj);
                            }
                            flushObject = null;
                        } else {
                            throw new XMLStreamException("Invalid Staring element");
                        }
                    }
                } else {
                    if (!stack.isEmpty()) {
                        stackObj = stack.peek();
                        if (stackObj.getName().equals(localName)) {
                            flushObject = null;
                            if (stackObj.getType() == JSONType.NESTED_ARRAY) {
                                fillMiniStack(stackObj);
                                jsonWriter.beginObject();
                                processedJsonObjects.push(stackObj);
                            }
                        } else {
                            throw new XMLStreamException("Invalid Staring element");
                        }
                    } else {
                        throw new XMLStreamException("Invalid Starting  element");
                    }
                }
            } else {
                JsonObject queObj = miniStack.peek();
                if (queObj.getName().equals(localName)) {
                    if (flushObject != null) {
                        popStack();
                        writeEndJson(flushObject);
                        flushObject = null;
                    }
                    if (topNestedArrayObj != null && (queObj.getType() == JSONType.NESTED_OBJECT
                            || queObj.getType() == JSONType.NESTED_ARRAY)) {
                        processedJsonObjects.push(queObj);
                    }
                    writeStartJson(queObj);
                    stack.push(miniStack.pop());
                } else if (!stack.isEmpty()) {
                    stackObj = stack.peek();
                    if (stackObj.getName().equals(localName)) {
                        flushObject = null;
                        if (stackObj.getType() == JSONType.NESTED_ARRAY) {
                            fillMiniStack(stackObj);
                            jsonWriter.beginObject();
                            processedJsonObjects.push(stackObj);
                        }
                    } else {
                        throw new XMLStreamException("Invalid Staring element");
                    }
                }
            }
        } catch (IOException e) {
            throw new XMLStreamException(" Json Writer throw an error");
        }
    }

    /**
     * Writes a start tag to the output
     *
     * @param namespaceURI the namespaceURI of the prefix to use, may not be null
     * @param localName    local name of the tag, may not be null
     * @throws javax.xml.stream.XMLStreamException
     *          if the namespace URI has not been bound to a prefix and
     *          javax.xml.stream.isRepairingNamespaces has not been set to true
     */

    public void writeStartElement(String namespaceURI, String localName) throws XMLStreamException {
        writeStartElement(localName);
    }

    /**
     * Writes a start tag to the output
     *
     * @param localName    local name of the tag, may not be null
     * @param prefix       the prefix of the tag, may not be null
     * @param namespaceURI the uri to bind the prefix to, may not be null
     * @throws javax.xml.stream.XMLStreamException
     *
     */

    public void writeStartElement(String prefix, String localName, String namespaceURI) throws XMLStreamException {
        writeStartElement(localName);
    }

    /**
     * Writes an empty element tag to the output
     *
     * @param namespaceURI the uri to bind the tag to, may not be null
     * @param localName    local name of the tag, may not be null
     * @throws javax.xml.stream.XMLStreamException
     *          if the namespace URI has not been bound to a prefix and
     *          javax.xml.stream.isRepairingNamespaces has not been set to true
     */

    public void writeEmptyElement(String namespaceURI, String localName) throws XMLStreamException {
        throw new UnsupportedOperationException("Method is not implemented");
    }

    /**
     * Writes an empty element tag to the output
     *
     * @param prefix       the prefix of the tag, may not be null
     * @param localName    local name of the tag, may not be null
     * @param namespaceURI the uri to bind the tag to, may not be null
     * @throws javax.xml.stream.XMLStreamException
     *
     */

    public void writeEmptyElement(String prefix, String localName, String namespaceURI) throws XMLStreamException {
        throw new UnsupportedOperationException("Method is not implemented");
    }

    /**
     * Writes an empty element tag to the output
     *
     * @param localName local name of the tag, may not be null
     * @throws javax.xml.stream.XMLStreamException
     *
     */

    public void writeEmptyElement(String localName) throws XMLStreamException {
        throw new UnsupportedOperationException("Method is not implemented");
    }

    /**
     * Writes an end tag to the output relying on the internal
     * state of the writer to determine the prefix and local name
     * of the event.
     *
     * @throws javax.xml.stream.XMLStreamException
     *
     */

    public void writeEndElement() throws XMLStreamException {
        if (!isProcessed) {
            try {
                process();
            } catch (IOException e) {
                throw new XMLStreamException("Error occours while write first begin object ");
            }
        }
        JsonObject stackObj;
        try {
            if (flushObject != null) {
                if (topNestedArrayObj != null && flushObject.getType() == JSONType.NESTED_ARRAY &&
                        flushObject.equals(topNestedArrayObj.getName())) {
                    topNestedArrayObj = null;
                    processedJsonObjects.clear();
                }
                popStack();
                writeEndJson(flushObject);
                flushObject = null;
                writeEndElement();
            } else {
                if (stack.peek().getType() == JSONType.ARRAY) {
                    flushObject = stack.peek();
                } else if (stack.peek().getType() == JSONType.NESTED_ARRAY) {
                    flushObject = stack.peek();
                    jsonWriter.endObject();
                } else {
                    stackObj = popStack();
                    writeEndJson(stackObj);
                }
            }
        } catch (IOException e) {
            throw new XMLStreamException("Json writer throw an exception");
        }
    }

    /**
     * Closes any start tags and writes corresponding end tags.
     *
     * @throws javax.xml.stream.XMLStreamException
     *
     */

    public void writeEndDocument() throws XMLStreamException {
        if (!isProcessed) {
            try {
                process();
            } catch (IOException e) {
                throw new XMLStreamException("Error occours while write first begin object ");
            }
        }
        if (queue.isEmpty() && stack.isEmpty()) {
            try {
                if (flushObject != null) {
                    writeEndJson(flushObject);
                }
                jsonWriter.endObject();
                jsonWriter.flush();
                jsonWriter.close();
            } catch (IOException e) {
                throw new XMLStreamException("JsonWriter threw an exception", e);
            }
        } else {
            throw new XMLStreamException("Invalid xml element");
        }
    }

    /**
     * Close this writer and free any resources associated with the
     * writer.  This must not close the underlying output stream.
     *
     * @throws javax.xml.stream.XMLStreamException
     *
     */

    public void close() throws XMLStreamException {
        try {
            jsonWriter.close();
        } catch (IOException e) {
            throw new RuntimeException("Error occur while closing JsonWriter");
        }
    }

    /**
     * Write any cached data to the underlying output mechanism.
     *
     * @throws javax.xml.stream.XMLStreamException
     *
     */
    
    public void flush() throws XMLStreamException {
    }

    /**
     * Writes an attribute to the output stream without
     * a prefix.
     *
     * @param localName the local name of the attribute
     * @param value     the value of the attribute
     * @throws IllegalStateException if the current state does not allow Attribute writing
     * @throws javax.xml.stream.XMLStreamException
     *
     */

    public void writeAttribute(String localName, String value) throws XMLStreamException {
        throw new UnsupportedOperationException("Method is not implemented");
    }

    /**
     * Writes an attribute to the output stream
     *
     * @param prefix       the prefix for this attribute
     * @param namespaceURI the uri of the prefix for this attribute
     * @param localName    the local name of the attribute
     * @param value        the value of the attribute
     * @throws IllegalStateException if the current state does not allow Attribute writing
     * @throws javax.xml.stream.XMLStreamException
     *                               if the namespace URI has not been bound to a prefix and
     *                               javax.xml.stream.isRepairingNamespaces has not been set to true
     */

    public void writeAttribute(String prefix, String namespaceURI, String localName, String value) throws XMLStreamException {
        // GsonXMLStreamReader doesn't write Attributes
    }

    /**
     * Writes an attribute to the output stream
     *
     * @param namespaceURI the uri of the prefix for this attribute
     * @param localName    the local name of the attribute
     * @param value        the value of the attribute
     * @throws IllegalStateException if the current state does not allow Attribute writing
     * @throws javax.xml.stream.XMLStreamException
     *                               if the namespace URI has not been bound to a prefix and
     *                               javax.xml.stream.isRepairingNamespaces has not been set to true
     */

    public void writeAttribute(String namespaceURI, String localName, String value) throws XMLStreamException {
        throw new UnsupportedOperationException("Method is not implemented");
    }

    /**
     * Writes a namespace to the output stream
     * If the prefix argument to this method is the empty string,
     * "xmlns", or null this method will delegate to writeDefaultNamespace
     *
     * @param prefix       the prefix to bind this namespace to
     * @param namespaceURI the uri to bind the prefix to
     * @throws IllegalStateException if the current state does not allow Namespace writing
     * @throws javax.xml.stream.XMLStreamException
     *
     */

    public void writeNamespace(String prefix, String namespaceURI) throws XMLStreamException {
    }

    /**
     * Writes the default namespace to the stream
     *
     * @param namespaceURI the uri to bind the default namespace to
     * @throws IllegalStateException if the current state does not allow Namespace writing
     * @throws javax.xml.stream.XMLStreamException
     *
     */

    public void writeDefaultNamespace(String namespaceURI) throws XMLStreamException {
        // do nothing
    }

    /**
     * Writes an xml comment with the data enclosed
     *
     * @param data the data contained in the comment, may be null
     * @throws javax.xml.stream.XMLStreamException
     *
     */

    public void writeComment(String data) throws XMLStreamException {
        throw new UnsupportedOperationException("Method is not implemented");
    }

    /**
     * Writes a processing instruction
     *
     * @param target the target of the processing instruction, may not be null
     * @throws javax.xml.stream.XMLStreamException
     *
     */

    public void writeProcessingInstruction(String target) throws XMLStreamException {
        throw new UnsupportedOperationException("Method is not implemented");
    }

    /**
     * Writes a processing instruction
     *
     * @param target the target of the processing instruction, may not be null
     * @param data   the data contained in the processing instruction, may not be null
     * @throws javax.xml.stream.XMLStreamException
     *
     */

    public void writeProcessingInstruction(String target, String data) throws XMLStreamException {
        throw new UnsupportedOperationException("Method is not implemented");
    }

    /**
     * Writes a CData section
     *
     * @param data the data contained in the CData Section, may not be null
     * @throws javax.xml.stream.XMLStreamException
     *
     */

    public void writeCData(String data) throws XMLStreamException {
        throw new UnsupportedOperationException("Method is not implemented");
    }

    /**
     * Write a DTD section.  This string represents the entire doctypedecl production
     * from the XML 1.0 specification.
     *
     * @param dtd the DTD to be written
     * @throws javax.xml.stream.XMLStreamException
     *
     */

    public void writeDTD(String dtd) throws XMLStreamException {
        throw new UnsupportedOperationException("Method is not implemented");
    }

    /**
     * Writes an entity reference
     *
     * @param name the name of the entity
     * @throws javax.xml.stream.XMLStreamException
     *
     */

    public void writeEntityRef(String name) throws XMLStreamException {
        throw new UnsupportedOperationException("Method is not implemented");
    }

    /**
     * Write the XML Declaration. Defaults the XML version to 1.0, and the encoding to utf-8
     *
     * @throws javax.xml.stream.XMLStreamException
     *
     */

    public void writeStartDocument() throws XMLStreamException {
        if (!isProcessed) {
            try {
                process();
            } catch (IOException e) {
                throw new XMLStreamException("Error occur while write first begin object ");
            }
        }
    }

    /**
     * Write the XML Declaration. Defaults the XML version to 1.0
     *
     * @param version version of the xml document
     * @throws javax.xml.stream.XMLStreamException
     *
     */

    public void writeStartDocument(String version) throws XMLStreamException {
        throw new UnsupportedOperationException("Method is not implemented");
    }

    /**
     * Write the XML Declaration.  Note that the encoding parameter does
     * not set the actual encoding of the underlying output.  That must
     * be set when the instance of the XMLStreamWriter is created using the
     * XMLOutputFactory
     *
     * @param encoding encoding of the xml declaration
     * @param version  version of the xml document
     * @throws javax.xml.stream.XMLStreamException
     *          If given encoding does not match encoding
     *          of the underlying stream
     */

    public void writeStartDocument(String encoding, String version) throws XMLStreamException {
        if (!isProcessed) {
            try {
                process();
            } catch (IOException e) {
                throw new XMLStreamException("Error occur while trying to write start document element", e);
            }
        }
    }

    /**
     * Write text to the output
     *
     * @param text the value to write
     * @throws javax.xml.stream.XMLStreamException
     *
     */

    public void writeCharacters(String text) throws XMLStreamException {
        if (!isProcessed) {
            try {
                process();
            } catch (IOException e) {
                throw new XMLStreamException("Error occur while trying to write first begin object ", e);
            }
        }
        try {
            JsonObject peek = stack.peek();
            String valueType = peek.getValueType();
            if (valueType.equals("string")) {
                jsonWriter.value(text);
            } else if (valueType.equals("int")) {
                Number num = new Integer(text);
                jsonWriter.value(num);
            } else if (valueType.equals("long")) {
                jsonWriter.value(Long.valueOf(text));
            } else if (valueType.equals("double")) {
                jsonWriter.value(Double.valueOf(text));
            } else if (valueType.equals("boolean")) {
                jsonWriter.value(Boolean.valueOf(text));
            } else {
                jsonWriter.value(text);
            }
        } catch (IOException e) {
            throw new XMLStreamException("JsonWriter throw an exception");
        }
    }

    /**
     * Write text to the output
     *
     * @param text  the value to write
     * @param start the starting position in the array
     * @param len   the number of characters to write
     * @throws javax.xml.stream.XMLStreamException
     *
     */

    public void writeCharacters(char[] text, int start, int len) throws XMLStreamException {
        throw new UnsupportedOperationException("Method is not implemented");
    }

    /**
     * Gets the prefix the uri is bound to
     *
     * @return the prefix or null
     * @throws javax.xml.stream.XMLStreamException
     *
     */

    public String getPrefix(String uri) throws XMLStreamException {
        return uriPrefixMap.get(uri);
    }

    /**
     * Sets the prefix the uri is bound to.  This prefix is bound
     * in the scope of the current START_ELEMENT / END_ELEMENT pair.
     * If this method is called before a START_ELEMENT has been written
     * the prefix is bound in the root scope.
     *
     * @param prefix the prefix to bind to the uri, may not be null
     * @param uri    the uri to bind to the prefix, may be null
     * @throws javax.xml.stream.XMLStreamException
     *
     */

    public void setPrefix(String prefix, String uri) throws XMLStreamException {
        uriPrefixMap.put(uri, prefix);
    }

    /**
     * Binds a URI to the default namespace
     * This URI is bound
     * in the scope of the current START_ELEMENT / END_ELEMENT pair.
     * If this method is called before a START_ELEMENT has been written
     * the uri is bound in the root scope.
     *
     * @param uri the uri to bind to the default namespace, may be null
     * @throws javax.xml.stream.XMLStreamException
     *
     */

    public void setDefaultNamespace(String uri) throws XMLStreamException {
        //do nothing. 
    }

    /**
     * Sets the current namespace context for prefix and uri bindings.
     * This context becomes the root namespace context for writing and
     * will replace the current root namespace context.  Subsequent calls
     * to setPrefix and setDefaultNamespace will bind namespaces using
     * the context passed to the method as the root context for resolving
     * namespaces.  This method may only be called once at the start of
     * the document.  It does not cause the namespaces to be declared.
     * If a namespace URI to prefix mapping is found in the namespace
     * context it is treated as declared and the prefix may be used
     * by the StreamWriter.
     *
     * @param context the namespace context to use for this writer, may not be null
     * @throws javax.xml.stream.XMLStreamException
     *
     */

    public void setNamespaceContext(NamespaceContext context) throws XMLStreamException {
        throw new UnsupportedOperationException("Method is not implemented");
    }

    /**
     * Returns the current namespace context.
     *
     * @return the current NamespaceContext
     */

    public NamespaceContext getNamespaceContext() {
        return new GsonNamespaceConext();
    }

    /**
     * Get the value of a feature/property from the underlying implementation
     *
     * @param name The name of the property, may not be null
     * @return The value of the property
     * @throws IllegalArgumentException if the property is not supported
     * @throws NullPointerException     if the name is null
     */

    public Object getProperty(String name) throws IllegalArgumentException {
        return null;
    }
}
