/*
 * Copyright (c) 1998, 2020 Oracle and/or its affiliates. All rights reserved.
 *
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Public License v. 2.0 which is available at
 * http://www.eclipse.org/legal/epl-2.0,
 * or the Eclipse Distribution License v. 1.0 which is available at
 * http://www.eclipse.org/org/documents/edl-v10.php.
 *
 * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
 */

// Contributors:
//      Denise Smith - November 2, 2009
package org.eclipse.persistence.oxm.record;

import java.io.ByteArrayOutputStream;
import java.io.UnsupportedEncodingException;

import org.eclipse.persistence.exceptions.XMLMarshalException;
import org.eclipse.persistence.internal.oxm.Constants;
import org.eclipse.persistence.internal.oxm.NamespaceResolver;
import org.eclipse.persistence.internal.oxm.XPathFragment;
import org.eclipse.persistence.internal.oxm.record.XMLFragmentReader;
import org.w3c.dom.Attr;
import org.w3c.dom.Node;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;

/**
 * <p>Use this type of MarshalRecord when the marshal target is an OutputStream and the
 * XML should be formatted with carriage returns and indenting. This type is only
 * used if the encoding of the OutputStream is UTF-8</p>
 * <p><code>
 * XMLContext xmlContext = new XMLContext("session-name");<br>
 * XMLMarshaller xmlMarshaller = xmlContext.createMarshaller();<br>
 * FormattedOutputStreamRecord record = new FormattedOutputStreamRecord();<br>
 * record.setOutputStream(myOutputStream);<br>
 * xmlMarshaller.marshal(myObject, record);<br>
 * </code></p>
 * <p>If the marshal(OutputStream) and setFormattedOutput(true) method is called on
 * XMLMarshaller and the encoding is UTF-8, then the OutputStream is automatically wrapped
 * in a FormattedOutputStreamRecord.</p>
 * <p><code>
 * XMLContext xmlContext = new XMLContext("session-name");<br>
 * XMLMarshaller xmlMarshaller = xmlContext.createMarshaller();<br>
 * xmlMarshaller xmlMarshaller.setFormattedOutput(true);<br>
 * xmlMarshaller.marshal(myObject, myOutputStream);<br>
 * </code></p>
 * @see org.eclipse.persistence.oxm.XMLMarshaller
 */
public class FormattedOutputStreamRecord extends OutputStreamRecord {

    private byte[] cr = Constants.cr().getBytes(Constants.DEFAULT_CHARSET);
    private byte[] tab;
    private int numberOfTabs;
    private boolean complexType;
    private boolean isLastEventText;

    public FormattedOutputStreamRecord() {
        super();
        numberOfTabs = 0;
        complexType = true;
        isLastEventText = false;
    }

    private byte[] tab() {
        if (tab == null) {
            String sTab = getMarshaller().getIndentString();
            // Escape the tab using writeValue
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            writeValue(sTab, true, false, baos);
            tab = baos.toByteArray();
        }
        return tab;
    }

    /**
     * INTERNAL:
     */
    @Override
    public void endDocument() {
        outputStreamWrite(cr);
    }

    /**
     * INTERNAL:
     */
    @Override
    public void startDocument(String encoding, String version) {
        super.startDocument(encoding, version);
        outputStreamWrite(cr);
    }

    /**
     * INTERNAL
     */
    @Override
    public void writeHeader() {
        outputStreamWrite(getMarshaller().getXmlHeader().getBytes());
        outputStreamWrite(cr);
    }

    /**
     * INTERNAL:
     */
    @Override
    public void openStartElement(XPathFragment xPathFragment, NamespaceResolver namespaceResolver) {
        this.addPositionalNodes(xPathFragment, namespaceResolver);
        if (isStartElementOpen) {
            outputStreamWrite(CLOSE_ELEMENT);
        }
        if (!isLastEventText) {
            if (numberOfTabs > 0) {
                outputStreamWrite(cr);
            }
            outputStreamWriteTab();
        }
        isStartElementOpen = true;
        outputStreamWrite(OPEN_START_ELEMENT);
        byte[] prefixBytes = getPrefixBytes(xPathFragment);
        if(null != prefixBytes) {
            outputStreamWrite(prefixBytes);
            outputStreamWrite((byte)':');
        }
        outputStreamWrite(xPathFragment.getLocalNameBytes());
        if(xPathFragment.isGeneratedPrefix()){
            namespaceDeclaration(xPathFragment.getPrefix(), xPathFragment.getNamespaceURI());
        }
        numberOfTabs++;
        isLastEventText = false;
    }

    /**
     * INTERNAL:
     */
    @Override
    public void element(XPathFragment frag) {
        isLastEventText = false;
        if (isStartElementOpen) {
            outputStreamWrite(CLOSE_ELEMENT);
            isStartElementOpen = false;
        }
        outputStreamWrite(cr);
        outputStreamWriteTab();
        super.element(frag);
    }

    /**
     * INTERNAL:
     */
    @Override
    public void endElement(XPathFragment xPathFragment, NamespaceResolver namespaceResolver) {
        isLastEventText = false;
        numberOfTabs--;
        if (isStartElementOpen) {
            outputStreamWrite((byte) '/');
            outputStreamWrite((byte) '>');
            isStartElementOpen = false;
            return;
        }
        if (complexType) {
            outputStreamWrite(cr);
            outputStreamWriteTab();
        } else {
            complexType = true;
        }
        super.endElement(xPathFragment, namespaceResolver);
    }

    /**
     * INTERNAL:
     */
    @Override
    public void characters(String value) {
        super.characters(value);
        isLastEventText = true;
        complexType = false;
    }

    /**
     * INTERNAL:
     */
    @Override
    public void cdata(String value) {
        //Format the CDATA on it's own line
        if(isStartElementOpen) {
            outputStreamWrite(CLOSE_ELEMENT);
            isStartElementOpen = false;
        }
        super.cdata(value);
        complexType=false;
    }

    /**
     * Receive notification of a node.
     * @param node The Node to be added to the document
     * @param namespaceResolver The NamespaceResolver can be used to resolve the
     * namespace URI/prefix of the node
     */
    @Override
    public void node(Node node, NamespaceResolver namespaceResolver, String newNamespace, String newName) {
        if (node.getNodeType() == Node.ATTRIBUTE_NODE) {
            Attr attr = (Attr) node;
            String resolverPfx = null;
            if (namespaceResolver != null) {
                resolverPfx = namespaceResolver.resolveNamespaceURI(attr.getNamespaceURI());
            }
            // If the namespace resolver contains a prefix for the attribute's URI,
            // use it instead of what is set on the attribute
            if (resolverPfx != null) {
                attribute(attr.getNamespaceURI(), Constants.EMPTY_STRING, resolverPfx+Constants.COLON+attr.getLocalName(), attr.getNodeValue());
            } else {
                attribute(attr.getNamespaceURI(), Constants.EMPTY_STRING, attr.getName(), attr.getNodeValue());
                // May need to declare the URI locally
                if (attr.getNamespaceURI() != null) {
                    namespaceDeclaration(attr.getPrefix(),  attr.getNamespaceURI());
                }
            }
        } else if (node.getNodeType() == Node.TEXT_NODE) {
            characters(node.getNodeValue());
        } else {
            try {
                FormattedOutputStreamRecordContentHandler handler = new FormattedOutputStreamRecordContentHandler();
                XMLFragmentReader xfragReader = new XMLFragmentReader(namespaceResolver);
                xfragReader.setContentHandler(handler);
                xfragReader.setProperty(Constants.LEXICAL_HANDLER_PROPERTY, handler);
                xfragReader.parse(node, newNamespace, newName);
            } catch (SAXException sex) {
                throw XMLMarshalException.marshalException(sex);
            }
        }
    }

    /**
     * This class will typically be used in conjunction with an XMLFragmentReader.
     * The XMLFragmentReader will walk a given XMLFragment node and report events
     * to this class - the event's data is then written to the enclosing class'
     * writer.
     *
     * @see org.eclipse.persistence.internal.oxm.record.XMLFragmentReader
     * @see org.eclipse.persistence.oxm.record.WriterRecord.WriterRecordContentHandler
     */
    private class FormattedOutputStreamRecordContentHandler extends OutputStreamRecordContentHandler {
        // --------------------- CONTENTHANDLER METHODS --------------------- //
        @Override
        public void startElement(String namespaceURI, String localName, String qName, Attributes atts) throws SAXException {
            try {
                if (isStartElementOpen) {
                    outputStreamWrite(CLOSE_ELEMENT);
                }
                if (!isLastEventText) {
                    outputStreamWrite(cr);
                    outputStreamWriteTab();
                }
                outputStreamWrite(OPEN_START_ELEMENT);
                outputStreamWrite(qName.getBytes(Constants.DEFAULT_XML_ENCODING));
                numberOfTabs++;
                isStartElementOpen = true;
                isLastEventText = false;
                // Handle attributes
                handleAttributes(atts);
                // Handle prefix mappings
                writePrefixMappings();
            } catch (UnsupportedEncodingException e) {
                throw XMLMarshalException.marshalException(e);
            }
        }

        @Override
        public void endElement(String namespaceURI, String localName, String qName) throws SAXException {
            isLastEventText = false;
            numberOfTabs--;
            if (isStartElementOpen) {
                outputStreamWrite((byte) '/');
                outputStreamWrite((byte) '>');
                isStartElementOpen = false;
                complexType = true;
                return;
            }
            if (complexType) {
                outputStreamWrite(cr);
                outputStreamWriteTab();
            } else {
                complexType = true;
            }
            super.endElement(namespaceURI, localName, qName);
        }

        @Override
        public void characters(char[] ch, int start, int length) throws SAXException {
            if (isProcessingCData) {
                cdata(new String (ch, start, length));
                return;
            }
            if (new String(ch).trim().length() == 0) {
                return;
            }
            super.characters(ch, start, length);
            isLastEventText = true;
            complexType = false;
        }

        // --------------------- LEXICALHANDLER METHODS --------------------- //
        @Override
        public void comment(char[] ch, int start, int length) throws SAXException {
            if (isStartElementOpen) {
                outputStreamWrite(CLOSE_ELEMENT);
                outputStreamWrite(cr);
                isStartElementOpen = false;
            }
            writeComment(ch, start, length);
            complexType = false;
        }
    }

    private void outputStreamWriteTab() {
        for (int x = 0; x < numberOfTabs; x++) {
            outputStreamWrite(tab());
        }
    }

}
