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

import com.squareup.moshi.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 MoshiXMLStreamWriter implements XMLStreamWriter {

    Log log = LogFactory.getLog(MoshiXMLStreamWriter.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 MoshiXMLStreamWriter(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("MoshiXMLStreamWriter.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 ex) {
            log.error(ex.getMessage(), ex);
            throw new XMLStreamException("Bad Response");
        }
    }

    /**
     * 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 {
        // MoshiXMLStreamReader 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 MoshiNamespaceContext();
    }

    /**
     * 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;
    }
}
