/* AbstractWriter.java --
   Copyright (C) 2005 Free Software Foundation, Inc.

This file is part of GNU Classpath.

GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
 
GNU Classpath 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 for more details.

You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING.  If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.

Linking this library statically or dynamically with other modules is
making a combined work based on this library.  Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.

As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module.  An independent module is a module which is not derived from
or based on this library.  If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so.  If you do not wish to do so, delete this
exception statement from your version. */

package javax.swing.text;

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

/**
 * This is an abstract base class for writing Document instances to a
 * Writer.  A concrete subclass must implement a method to iterate
 * over the Elements of the Document and correctly format them.
 */
public abstract class AbstractWriter
{
  /**
   * The default line separator character.
   * @specnote although this is a constant, it is not static in the JDK
   */
  protected static final char NEWLINE = '\n';

  // Where we write.
  private Writer writer;
  // How we iterate over the document.
  private ElementIterator iter;
  // The document over which we iterate.
  private Document document;
  // Maximum number of characters per line.
  private int maxLineLength = 100;
  // Number of characters we have currently written.
  private int lineLength;
  // True if we can apply line wrapping.
  private boolean canWrapLines;	// FIXME default?
  // The number of spaces per indentation level.
  private int indentSpace = 2;
  // The current indentation level.
  private int indentLevel;
  // True if we have indented this line.
  private boolean indented;
  // Starting offset in document.
  private int startOffset;
  // Ending offset in document.
  private int endOffset;
  // The line separator string.
  private String lineSeparator = "" + NEWLINE;
  // The characters making up the line separator.
  private char[] lineSeparatorChars = lineSeparator.toCharArray();

  /**
   * Create a new AbstractWriter with the indicated Writer and
   * Document.  The full range of the Document will be used.  The
   * internal ElementIterator will be initialized with the Document's
   * root node.
   */
  protected AbstractWriter(Writer writer, Document doc)
  {
    this.writer = writer;
    this.iter = new ElementIterator(doc);
    this.document = doc;
    this.startOffset = 0;
    this.endOffset = doc.getLength();
  }

  /**
   * Create a new AbstractWriter with the indicated Writer and
   * Document.  The full range of the Document will be used.  The
   * internal ElementIterator will be initialized with the Document's
   * root node.
   */
  protected AbstractWriter(Writer writer, Document doc, int pos, int len)
  {
    this.writer = writer;
    this.iter = new ElementIterator(doc);
    this.document = doc;
    this.startOffset = pos;
    this.endOffset = pos + len;
  }

  /**
   * Create a new AbstractWriter with the indicated Writer and
   * Element.  The full range of the Element will be used.
   */
  protected AbstractWriter(Writer writer, Element elt)
  {
    this.writer = writer;
    this.iter = new ElementIterator(elt);
    this.document = elt.getDocument();
    this.startOffset = elt.getStartOffset();
    this.endOffset = elt.getEndOffset();
  }

  /**
   * Create a new AbstractWriter with the indicated Writer and
   * Element.  The full range of the Element will be used.  The range
   * will be limited to the indicated range of the Document.
   */
  protected AbstractWriter(Writer writer, Element elt, int pos, int len)
  {
    this.writer = writer;
    this.iter = new ElementIterator(elt);
    this.document = elt.getDocument();
    this.startOffset = pos;
    this.endOffset = pos + len;
  }

  /**
   * Return the ElementIterator for this writer.
   */
  protected ElementIterator getElementIterator()
  {
    return iter;
  }

  /**
   * Return the Writer to which we are writing.
   * @since 1.3
   */
  protected Writer getWriter()
  {
    return writer;
  }

  /**
   * Return this writer's Document.
   */
  protected Document getDocument()
  {
    return document;
  }

  /**
   * This method must be overridden by a concrete subclass.  It is
   * responsible for iterating over the Elements of the Document and
   * writing them out. 
   */
  protected abstract void write() throws IOException, BadLocationException;

  /**
   * Return the text of the Document that is associated with the given
   * Element.  If the Element is not a leaf Element, this will throw
   * BadLocationException.
   *
   * @throws BadLocationException if the element is not a leaf
   */
  protected String getText(Element elt) throws BadLocationException
  {
    if (! elt.isLeaf())
      throw new BadLocationException("Element is not a leaf",
				     elt.getStartOffset());
    return document.getText(elt.getStartOffset(), 
			    elt.getEndOffset() - elt.getStartOffset());
  }

  /**
   * This method calls Writer.write on the indicated data, and updates
   * the current line length.  This method does not look for newlines
   * in the written data; the caller is responsible for that.
   *
   * @since 1.3
   */
  protected void output(char[] data, int start, int len) throws IOException
  {
    writer.write(data, start, len);
    lineLength += len;
  }

  /**
   * Write a line separator using the output method, and then reset
   * the current line length.
   *
   * @since 1.3
   */
  protected void writeLineSeparator() throws IOException
  {
    output(lineSeparatorChars, 0, lineSeparatorChars.length);
    lineLength = 0;
    indented = false;
  }

  /**
   * Write a single character.
   */
  protected void write(char ch) throws IOException
  {
    write(new char[] { ch }, 0, 1);
  }

  /**
   * Write a String.
   */
  protected void write(String s) throws IOException
  {
    char[] v = s.toCharArray();
    write(v, 0, v.length);
  }

  /**
   * Write a character array to the output Writer, properly handling
   * newlines and, if needed, wrapping lines as they are output.
   * @since 1.3
   */
  protected void write(char[] data, int start, int len) throws IOException
  {
    if (getCanWrapLines())
      {
	// FIXME: should we be handling newlines specially here?
	for (int i = 0; i < len; )
	  {
	    int start_i = i;
	    // Find next space.
	    while (i < len && data[start + i] != ' ')
	      ++i;
	    if (i < len && lineLength + i - start_i >= maxLineLength)
	      writeLineSeparator();
	    else if (i < len)
	      {
		// Write the trailing space.
		++i;
	      }
	    // Write out the text.
	    output(data, start + start_i, start + i - start_i);
	  }
      }
    else
      {
	int saved_i = start;
	for (int i = start; i < start + len; ++i)
	  {
	    if (data[i] == NEWLINE)
	      {
		output(data, saved_i, i - saved_i);
		writeLineSeparator();
	      }
	  }
	if (saved_i < start + len - 1)
	  output(data, saved_i, start + len - saved_i);
      }
  }

  /**
   * Indent this line by emitting spaces, according to the current
   * indent level and the current number of spaces per indent.  After
   * this method is called, the current line is no longer considered
   * to be empty, even if no spaces are actually written.
   */
  protected void indent() throws IOException
  {
    int spaces = indentLevel * indentSpace;
    if (spaces > 0)
      {
	char[] v = new char[spaces];
	Arrays.fill(v, ' ');
	write(v, 0, v.length);
      }
    indented = true;
  }

  /**
   * Return the index of the Document at which output starts.
   * @since 1.3
   */
  public int getStartOffset()
  {
    return startOffset;
  }

  /**
   * Return the index of the Document at which output ends.
   * @since 1.3
   */
  public int getEndOffset()
  {
    return endOffset;
  }

  /**
   * Return true if the Element's range overlaps our desired output
   * range; false otherwise.
   */
  protected boolean inRange(Element elt)
  {
    int eltStart = elt.getStartOffset();
    int eltEnd = elt.getEndOffset();
    return ((eltStart >= startOffset && eltStart < endOffset)
	    || (eltEnd >= startOffset && eltEnd < endOffset));
  }

  /**
   * Output the text of the indicated Element, properly clipping it to
   * the range of the Document specified when the AbstractWriter was
   * created.
   */
  protected void text(Element elt) throws BadLocationException, IOException
  {
    int eltStart = elt.getStartOffset();
    int eltEnd = elt.getEndOffset();

    eltStart = Math.max(eltStart, startOffset);
    eltEnd = Math.min(eltEnd, endOffset);
    write(document.getText(eltStart, eltEnd));
  }

  /**
   * Set the maximum line length.
   */
  protected void setLineLength(int maxLineLength)
  {
    this.maxLineLength = maxLineLength;
  }

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

  /**
   * Set the current line length.
   * @since 1.3
   */
  protected void setCurrentLineLength(int lineLength)
  {
    this.lineLength = lineLength;
  }

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

  /**
   * Return true if the line is empty, false otherwise.  The line is
   * empty if nothing has been written since the last newline, and
   * indent has not been invoked.
   */
  protected boolean isLineEmpty()
  {
    return lineLength == 0 && ! indented;
  }

  /**
   * Set the flag indicating whether lines will wrap.  This affects
   * the behavior of write().
   * @since 1.3
   */
  protected void setCanWrapLines(boolean canWrapLines)
  {
    this.canWrapLines = canWrapLines;
  }

  /**
   * Return true if lines printed via write() will wrap, false
   * otherwise.
   * @since 1.3
   */
  protected boolean getCanWrapLines()
  {
    return canWrapLines;
  }

  /**
   * Set the number of spaces per indent level.
   * @since 1.3
   */
  protected void setIndentSpace(int indentSpace)
  {
    this.indentSpace = indentSpace;
  }

  /**
   * Return the number of spaces per indent level.
   * @since 1.3
   */
  protected int getIndentSpace()
  {
    return indentSpace;
  }

  /**
   * Set the current line separator.
   * @since 1.3
   */
  public void setLineSeparator(String lineSeparator)
  {
    this.lineSeparator = lineSeparator;
    this.lineSeparatorChars = lineSeparator.toCharArray();
  }

  /**
   * Return the current line separator.
   * @since 1.3
   */
  public String getLineSeparator()
  {
    return lineSeparator;
  }

  /**
   * Increment the indent level.
   */
  protected void incrIndent()
  {
    ++indentLevel;
  }

  /**
   * Decrement the indent level.
   */
  protected void decrIndent()
  {
    --indentLevel;
  }

  /**
   * Return the current indent level.
   * @since 1.3
   */
  protected int getIndentLevel()
  {
    return indentLevel;
  }

  /**
   * Print the given AttributeSet as a sequence of assignment-like
   * strings, e.g. "key=value".
   */
  protected void writeAttributes(AttributeSet attrs) throws IOException
  {
    Enumeration e = attrs.getAttributeNames();
    while (e.hasMoreElements())
      {
	Object name = e.nextElement();
	Object val = attrs.getAttribute(name);
	write(name + "=" + val);
	writeLineSeparator();
      }
  }
}
