/*
 * Copyright (c) 1998, 2006, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

package javax.swing.text;

import java.io.Writer;
import java.io.IOException;
import java.util.Enumeration;

/**
 * AbstractWriter is an abstract class that actually
 * does the work of writing out the element tree
 * including the attributes.  In terms of how much is
 * written out per line, the writer defaults to 100.
 * But this value can be set by subclasses.
 *
 * @author Sunita Mani
 */

public abstract class AbstractWriter {

    private ElementIterator it;
    private Writer out;
    private int indentLevel = 0;
    private int indentSpace = 2;
    private Document doc = null;
    private int maxLineLength = 100;
    private int currLength = 0;
    private int startOffset = 0;
    private int endOffset = 0;
    // If (indentLevel * indentSpace) becomes >= maxLineLength, this will
    // get incremened instead of indentLevel to avoid indenting going greater
    // than line length.
    private int offsetIndent = 0;

    /**
     * String used for end of line. If the Document has the property
     * EndOfLineStringProperty, it will be used for newlines. Otherwise
     * the System property line.separator will be used. The line separator
     * can also be set.
     */
    private String lineSeparator;

    /**
     * True indicates that when writing, the line can be split, false
     * indicates that even if the line is > than max line length it should
     * not be split.
     */
    private boolean canWrapLines;

    /**
     * True while the current line is empty. This will remain true after
     * indenting.
     */
    private boolean isLineEmpty;

    /**
     * Used when indenting. Will contain the spaces.
     */
    private char[] indentChars;

    /**
     * Used when writing out a string.
     */
    private char[] tempChars;

    /**
     * This is used in <code>writeLineSeparator</code> instead of
     * tempChars. If tempChars were used it would mean write couldn't invoke
     * <code>writeLineSeparator</code> as it might have been passed
     * tempChars.
     */
    private char[] newlineChars;

    /**
     * Used for writing text.
     */
    private Segment segment;

    /**
     * How the text packages models newlines.
     * @see #getLineSeparator
     */
    protected static final char NEWLINE = '\n';


    /**
     * Creates a new AbstractWriter.
     * Initializes the ElementIterator with the default
     * root of the document.
     *
     * @param w a Writer.
     * @param doc a Document
     */
    protected AbstractWriter(Writer w, Document doc) {
        this(w, doc, 0, doc.getLength());
    }

    /**
     * Creates a new AbstractWriter.
     * Initializes the ElementIterator with the
     * element passed in.
     *
     * @param w a Writer
     * @param doc an Element
     * @param pos The location in the document to fetch the
     *   content.
     * @param len The amount to write out.
     */
    protected AbstractWriter(Writer w, Document doc, int pos, int len) {
        this.doc = doc;
        it = new ElementIterator(doc.getDefaultRootElement());
        out = w;
        startOffset = pos;
        endOffset = pos + len;
        Object docNewline = doc.getProperty(DefaultEditorKit.
                                       EndOfLineStringProperty);
        if (docNewline instanceof String) {
            setLineSeparator((String)docNewline);
        }
        else {
            String newline = null;
            try {
                newline = System.getProperty("line.separator");
            } catch (SecurityException se) {}
            if (newline == null) {
                // Should not get here, but if we do it means we could not
                // find a newline string, use \n in this case.
                newline = "\n";
            }
            setLineSeparator(newline);
        }
        canWrapLines = true;
    }

    /**
     * Creates a new AbstractWriter.
     * Initializes the ElementIterator with the
     * element passed in.
     *
     * @param w a Writer
     * @param root an Element
     */
    protected AbstractWriter(Writer w, Element root) {
        this(w, root, 0, root.getEndOffset());
    }

    /**
     * Creates a new AbstractWriter.
     * Initializes the ElementIterator with the
     * element passed in.
     *
     * @param w a Writer
     * @param root an Element
     * @param pos The location in the document to fetch the
     *   content.
     * @param len The amount to write out.
     */
    protected AbstractWriter(Writer w, Element root, int pos, int len) {
        this.doc = root.getDocument();
        it = new ElementIterator(root);
        out = w;
        startOffset = pos;
        endOffset = pos + len;
        canWrapLines = true;
    }

    /**
     * Returns the first offset to be output.
     *
     * @since 1.3
     */
    public int getStartOffset() {
        return startOffset;
    }

    /**
     * Returns the last offset to be output.
     *
     * @since 1.3
     */
    public int getEndOffset() {
        return endOffset;
    }

    /**
     * Fetches the ElementIterator.
     *
     * @return the ElementIterator.
     */
    protected ElementIterator getElementIterator() {
        return it;
    }

    /**
     * Returns the Writer that is used to output the content.
     *
     * @since 1.3
     */
    protected Writer getWriter() {
        return out;
    }

    /**
     * Fetches the document.
     *
     * @return the Document.
     */
    protected Document getDocument() {
        return doc;
    }

    /**
     * This method determines whether the current element
     * is in the range specified.  When no range is specified,
     * the range is initialized to be the entire document.
     * inRange() returns true if the range specified intersects
     * with the element's range.
     *
     * @param  next an Element.
     * @return boolean that indicates whether the element
     *         is in the range.
     */
    protected boolean inRange(Element next) {
        int startOffset = getStartOffset();
        int endOffset = getEndOffset();
        if ((next.getStartOffset() >= startOffset &&
             next.getStartOffset()  < endOffset) ||
            (startOffset >= next.getStartOffset() &&
             startOffset < next.getEndOffset())) {
            return true;
        }
        return false;
    }

    /**
     * This abstract method needs to be implemented
     * by subclasses.  Its responsibility is to
     * iterate over the elements and use the write()
     * methods to generate output in the desired format.
     */
    abstract protected void write() throws IOException, BadLocationException;

    /**
     * Returns the text associated with the element.
     * The assumption here is that the element is a
     * leaf element.  Throws a BadLocationException
     * when encountered.
     *
     * @param     elem an <code>Element</code>
     * @exception BadLocationException if pos represents an invalid
     *            location within the document
     * @return    the text as a <code>String</code>
     */
    protected String getText(Element elem) throws BadLocationException {
        return doc.getText(elem.getStartOffset(),
                           elem.getEndOffset() - elem.getStartOffset());
    }


    /**
     * Writes out text.  If a range is specified when the constructor
     * is invoked, then only the appropriate range of text is written
     * out.
     *
     * @param     elem an Element.
     * @exception IOException on any I/O error
     * @exception BadLocationException if pos represents an invalid
     *            location within the document.
     */
    protected void text(Element elem) throws BadLocationException,
                                             IOException {
        int start = Math.max(getStartOffset(), elem.getStartOffset());
        int end = Math.min(getEndOffset(), elem.getEndOffset());
        if (start < end) {
            if (segment == null) {
                segment = new Segment();
            }
            getDocument().getText(start, end - start, segment);
            if (segment.count > 0) {
                write(segment.array, segment.offset, segment.count);
            }
        }
    }

    /**
     * Enables subclasses to set the number of characters they
     * want written per line.   The default is 100.
     *
     * @param l the maximum line length.
     */
    protected void setLineLength(int l) {
        maxLineLength = l;
    }

    /**
     * Returns the maximum line length.
     *
     * @since 1.3
     */
    protected int getLineLength() {
        return maxLineLength;
    }

    /**
     * Sets the current line length.
     *
     * @since 1.3
     */
    protected void setCurrentLineLength(int length) {
        currLength = length;
        isLineEmpty = (currLength == 0);
    }

    /**
     * Returns the current line length.
     *
     * @since 1.3
     */
    protected int getCurrentLineLength() {
        return currLength;
    }

    /**
     * Returns true if the current line should be considered empty. This
     * is true when <code>getCurrentLineLength</code> == 0 ||
     * <code>indent</code> has been invoked on an empty line.
     *
     * @since 1.3
     */
    protected boolean isLineEmpty() {
        return isLineEmpty;
    }

    /**
     * Sets whether or not lines can be wrapped. This can be toggled
     * during the writing of lines. For example, outputting HTML might
     * set this to false when outputting a quoted string.
     *
     * @since 1.3
     */
    protected void setCanWrapLines(boolean newValue) {
        canWrapLines = newValue;
    }

    /**
     * Returns whether or not the lines can be wrapped. If this is false
     * no lineSeparator's will be output.
     *
     * @since 1.3
     */
    protected boolean getCanWrapLines() {
        return canWrapLines;
    }

    /**
     * Enables subclasses to specify how many spaces an indent
     * maps to. When indentation takes place, the indent level
     * is multiplied by this mapping.  The default is 2.
     *
     * @param space an int representing the space to indent mapping.
     */
    protected void setIndentSpace(int space) {
        indentSpace = space;
    }

    /**
     * Returns the amount of space to indent.
     *
     * @since 1.3
     */
    protected int getIndentSpace() {
        return indentSpace;
    }

    /**
     * Sets the String used to reprsent newlines. This is initialized
     * in the constructor from either the Document, or the System property
     * line.separator.
     *
     * @since 1.3
     */
    public void setLineSeparator(String value) {
        lineSeparator = value;
    }

    /**
     * Returns the string used to represent newlines.
     *
     * @since 1.3
     */
    public String getLineSeparator() {
        return lineSeparator;
    }

    /**
     * Increments the indent level. If indenting would cause
     * <code>getIndentSpace()</code> *<code>getIndentLevel()</code> to be >
     * than <code>getLineLength()</code> this will not cause an indent.
     */
    protected void incrIndent() {
        // Only increment to a certain point.
        if (offsetIndent > 0) {
            offsetIndent++;
        }
        else {
            if (++indentLevel * getIndentSpace() >= getLineLength()) {
                offsetIndent++;
                --indentLevel;
            }
        }
    }

    /**
     * Decrements the indent level.
     */
    protected void decrIndent() {
        if (offsetIndent > 0) {
            --offsetIndent;
        }
        else {
            indentLevel--;
        }
    }

    /**
     * Returns the current indentation level. That is, the number of times
     * <code>incrIndent</code> has been invoked minus the number of times
     * <code>decrIndent</code> has been invoked.
     *
     * @since 1.3
     */
    protected int getIndentLevel() {
        return indentLevel;
    }

    /**
     * Does indentation. The number of spaces written
     * out is indent level times the space to map mapping. If the current
     * line is empty, this will not make it so that the current line is
     * still considered empty.
     *
     * @exception IOException on any I/O error
     */
    protected void indent() throws IOException {
        int max = getIndentLevel() * getIndentSpace();
        if (indentChars == null || max > indentChars.length) {
            indentChars = new char[max];
            for (int counter = 0; counter < max; counter++) {
                indentChars[counter] = ' ';
            }
        }
        int length = getCurrentLineLength();
        boolean wasEmpty = isLineEmpty();
        output(indentChars, 0, max);
        if (wasEmpty && length == 0) {
            isLineEmpty = true;
        }
    }

    /**
     * Writes out a character. This is implemented to invoke
     * the <code>write</code> method that takes a char[].
     *
     * @param     ch a char.
     * @exception IOException on any I/O error
     */
    protected void write(char ch) throws IOException {
        if (tempChars == null) {
            tempChars = new char[128];
        }
        tempChars[0] = ch;
        write(tempChars, 0, 1);
    }

    /**
     * Writes out a string. This is implemented to invoke the
     * <code>write</code> method that takes a char[].
     *
     * @param     content a String.
     * @exception IOException on any I/O error
     */
    protected void write(String content) throws IOException {
        if (content == null) {
            return;
        }
        int size = content.length();
        if (tempChars == null || tempChars.length < size) {
            tempChars = new char[size];
        }
        content.getChars(0, size, tempChars, 0);
        write(tempChars, 0, size);
    }

    /**
     * Writes the line separator. This invokes <code>output</code> directly
     * as well as setting the <code>lineLength</code> to 0.
     *
     * @since 1.3
     */
    protected void writeLineSeparator() throws IOException {
        String newline = getLineSeparator();
        int length = newline.length();
        if (newlineChars == null || newlineChars.length < length) {
            newlineChars = new char[length];
        }
        newline.getChars(0, length, newlineChars, 0);
        output(newlineChars, 0, length);
        setCurrentLineLength(0);
    }

    /**
     * All write methods call into this one. If <code>getCanWrapLines()</code>
     * returns false, this will call <code>output</code> with each sequence
     * of <code>chars</code> that doesn't contain a NEWLINE, followed
     * by a call to <code>writeLineSeparator</code>. On the other hand,
     * if <code>getCanWrapLines()</code> returns true, this will split the
     * string, as necessary, so <code>getLineLength</code> is honored.
     * The only exception is if the current string contains no whitespace,
     * and won't fit in which case the line length will exceed
     * <code>getLineLength</code>.
     *
     * @since 1.3
     */
    protected void write(char[] chars, int startIndex, int length)
                   throws IOException {
        if (!getCanWrapLines()) {
            // We can not break string, just track if a newline
            // is in it.
            int lastIndex = startIndex;
            int endIndex = startIndex + length;
            int newlineIndex = indexOf(chars, NEWLINE, startIndex, endIndex);
            while (newlineIndex != -1) {
                if (newlineIndex > lastIndex) {
                    output(chars, lastIndex, newlineIndex - lastIndex);
                }
                writeLineSeparator();
                lastIndex = newlineIndex + 1;
                newlineIndex = indexOf(chars, '\n', lastIndex, endIndex);
            }
            if (lastIndex < endIndex) {
                output(chars, lastIndex, endIndex - lastIndex);
            }
        }
        else {
            // We can break chars if the length exceeds maxLength.
            int lastIndex = startIndex;
            int endIndex = startIndex + length;
            int lineLength = getCurrentLineLength();
            int maxLength = getLineLength();

            while (lastIndex < endIndex) {
                int newlineIndex = indexOf(chars, NEWLINE, lastIndex,
                                           endIndex);
                boolean needsNewline = false;
                boolean forceNewLine = false;

                lineLength = getCurrentLineLength();
                if (newlineIndex != -1 && (lineLength +
                              (newlineIndex - lastIndex)) < maxLength) {
                    if (newlineIndex > lastIndex) {
                        output(chars, lastIndex, newlineIndex - lastIndex);
                    }
                    lastIndex = newlineIndex + 1;
                    forceNewLine = true;
                }
                else if (newlineIndex == -1 && (lineLength +
                                (endIndex - lastIndex)) < maxLength) {
                    if (endIndex > lastIndex) {
                        output(chars, lastIndex, endIndex - lastIndex);
                    }
                    lastIndex = endIndex;
                }
                else {
                    // Need to break chars, find a place to split chars at,
                    // from lastIndex to endIndex,
                    // or maxLength - lineLength whichever is smaller
                    int breakPoint = -1;
                    int maxBreak = Math.min(endIndex - lastIndex,
                                            maxLength - lineLength - 1);
                    int counter = 0;
                    while (counter < maxBreak) {
                        if (Character.isWhitespace(chars[counter +
                                                        lastIndex])) {
                            breakPoint = counter;
                        }
                        counter++;
                    }
                    if (breakPoint != -1) {
                        // Found a place to break at.
                        breakPoint += lastIndex + 1;
                        output(chars, lastIndex, breakPoint - lastIndex);
                        lastIndex = breakPoint;
                        needsNewline = true;
                    }
                    else {
                        // No where good to break.

                        // find the next whitespace, or write out the
                        // whole string.
                            // maxBreak will be negative if current line too
                            // long.
                            counter = Math.max(0, maxBreak);
                            maxBreak = endIndex - lastIndex;
                            while (counter < maxBreak) {
                                if (Character.isWhitespace(chars[counter +
                                                                lastIndex])) {
                                    breakPoint = counter;
                                    break;
                                }
                                counter++;
                            }
                            if (breakPoint == -1) {
                                output(chars, lastIndex, endIndex - lastIndex);
                                breakPoint = endIndex;
                            }
                            else {
                                breakPoint += lastIndex;
                                if (chars[breakPoint] == NEWLINE) {
                                    output(chars, lastIndex, breakPoint++ -
                                           lastIndex);
                                forceNewLine = true;
                                }
                                else {
                                    output(chars, lastIndex, ++breakPoint -
                                              lastIndex);
                                needsNewline = true;
                                }
                            }
                            lastIndex = breakPoint;
                        }
                    }
                if (forceNewLine || needsNewline || lastIndex < endIndex) {
                    writeLineSeparator();
                    if (lastIndex < endIndex || !forceNewLine) {
                        indent();
                    }
                }
            }
        }
    }

    /**
     * Writes out the set of attributes as " <name>=<value>"
     * pairs. It throws an IOException when encountered.
     *
     * @param     attr an AttributeSet.
     * @exception IOException on any I/O error
     */
    protected void writeAttributes(AttributeSet attr) throws IOException {

        Enumeration names = attr.getAttributeNames();
        while (names.hasMoreElements()) {
            Object name = names.nextElement();
            write(" " + name + "=" + attr.getAttribute(name));
        }
    }

    /**
     * The last stop in writing out content. All the write methods eventually
     * make it to this method, which invokes <code>write</code> on the
     * Writer.
     * <p>This method also updates the line length based on
     * <code>length</code>. If this is invoked to output a newline, the
     * current line length will need to be reset as will no longer be
     * valid. If it is up to the caller to do this. Use
     * <code>writeLineSeparator</code> to write out a newline, which will
     * property update the current line length.
     *
     * @since 1.3
     */
    protected void output(char[] content, int start, int length)
                   throws IOException {
        getWriter().write(content, start, length);
        setCurrentLineLength(getCurrentLineLength() + length);
    }

    /**
     * Support method to locate an occurence of a particular character.
     */
    private int indexOf(char[] chars, char sChar, int startIndex,
                        int endIndex) {
        while(startIndex < endIndex) {
            if (chars[startIndex] == sChar) {
                return startIndex;
            }
            startIndex++;
        }
        return -1;
    }
}
