/* MinimalHTMLWriter.java --
   Copyright (C) 2006 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.html;

import javax.swing.text.AttributeSet;
import javax.swing.text.AbstractWriter;
import javax.swing.text.BadLocationException;
import javax.swing.text.DefaultStyledDocument;
import javax.swing.text.Element;
import javax.swing.text.ElementIterator;
import javax.swing.text.StyleConstants;
import javax.swing.text.Style;
import javax.swing.text.StyledDocument;
import java.io.Writer;
import java.io.IOException;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Enumeration;
import java.awt.Color;

/**
 * MinimalHTMLWriter,
 * A minimal AbstractWriter implementation for HTML.
 *
 * @author Sven de Marothy
 */
public class MinimalHTMLWriter extends AbstractWriter
{
  private StyledDocument doc;
  private Deque<String> tagStack;
  private boolean inFontTag = false;

  /**
   * Constructs a MinimalHTMLWriter.
   * @param w - a Writer, for output.
   * @param doc - the document
   */
  public MinimalHTMLWriter(Writer w, StyledDocument doc)
  {
    super(w, doc);
    this.doc = doc;
    tagStack = new ArrayDeque<String>();
  }

  /**
   * Constructs a MinimalHTMLWriter.
   * @param w - a Writer, for output.
   * @param doc - the document
   * @param pos - start position
   * @param len - length
   */
  public MinimalHTMLWriter(Writer w, StyledDocument doc, int pos, int len)
  {
    super(w, doc, pos, len);
    this.doc = doc;
    tagStack = new ArrayDeque<String>();
  }

  /**
   * Starts a span tag.
   */
  protected void startFontTag(String style) throws IOException
  {
    if( inFontTag() )
      endOpenTags();
    writeStartTag("<span style=\""+style+"\">");
    inFontTag = true;
  }

  /**
   * Returns whether the writer is within two span tags.
   */
  protected boolean inFontTag()
  {
    return inFontTag;
  }

  /**
   * Ends a span tag.
   */
  protected void endFontTag() throws IOException
  {
    writeEndTag("</span>");
    inFontTag = false;
  }

  /**
   * Write the entire HTML document.
   */
  public synchronized void write() throws IOException, BadLocationException
  {
    writeStartTag("<html>");
    writeHeader();
    writeBody();
    writeEndTag("</html>");
  }

  /**
   * Write a start tag and increment the indent.
   */
  protected void writeStartTag(String tag) throws IOException
  {
    indent();
    write(tag+NEWLINE);
    incrIndent();
  }

  /**
   * Write an ending tag and decrement the indent.
   */
  protected void writeEndTag(String endTag) throws IOException
  {
    decrIndent();
    indent();
    write(endTag+NEWLINE);
  }

  /**
   * Write the HTML header.
   */
  protected void writeHeader() throws IOException
  {
    writeStartTag("<head>");
    writeStartTag("<style>");
    writeStartTag("<!--");
    writeStyles();
    writeEndTag("-->");
    writeEndTag("</style>");
    writeEndTag("</head>");
  }

  /**
   * Write a paragraph start tag.
   */
  protected void writeStartParagraph(Element elem) throws IOException
  {
    indent();
    write("<p class=default>"+NEWLINE); // FIXME: Class value = ?
    incrIndent();
  }

  /**
   * Write a paragraph end tag, closes any other open tags.
   */
  protected void writeEndParagraph() throws IOException
  {
    endOpenTags();
    writeEndTag("</p>");
  }

  /**
   * Writes the body of the HTML document.
   */
  protected void writeBody() throws IOException, BadLocationException
  {
    writeStartTag("<body>");

    ElementIterator ei = getElementIterator();
    Element e = ei.first();
    boolean inParagraph = false;
    do
      {
        if( e.isLeaf() )
          {
            boolean hasNL = (getText(e).indexOf(NEWLINE) != -1);
            if( !inParagraph && hasText( e ) )
              {
                writeStartParagraph(e);
                inParagraph = true;
              }

            if( hasText( e ) )
              writeContent(e, true);

            if( hasNL && inParagraph )
              {
                writeEndParagraph();
                inParagraph = false;
              }
            else
              endOpenTags();
          }
      }
    while((e = ei.next()) != null);

    writeEndTag("</body>");
  }

  protected void text(Element elem) throws IOException, BadLocationException
  {
    write( getText(elem).trim() );
  }

  /**
   * Write bold, indent and underline tags.
   */
  protected void writeHTMLTags(AttributeSet attr) throws IOException
  {
    if(attr.getAttribute(StyleConstants.Bold) != null)
      if(((Boolean)attr.getAttribute(StyleConstants.Bold)).booleanValue())
        {
          write("<b>");
          tagStack.push("</b>");
        }
    if(attr.getAttribute(StyleConstants.Italic) != null)
      if(((Boolean)attr.getAttribute(StyleConstants.Italic)).booleanValue())
        {
          write("<i>");
          tagStack.push("</i>");
        }
    if(attr.getAttribute(StyleConstants.Underline) != null)
      if(((Boolean)attr.getAttribute(StyleConstants.Underline)).booleanValue())
        {
          write("<u>");
          tagStack.push("</u>");
        }
  }

  /**
   * Returns whether the element contains text or not.
   */
  protected boolean isText(Element elem)
  {
    return (elem.getEndOffset() != elem.getStartOffset());
  }

  /**
   * Writes the content of an element.
   */
  protected void writeContent(Element elem, boolean needsIndenting)
    throws IOException, BadLocationException
  {
    writeNonHTMLAttributes(elem.getAttributes());
    if(needsIndenting)
      indent();
    writeHTMLTags(elem.getAttributes());
    if( isText(elem) )
      text(elem);
    else
      writeLeaf(elem);

    endOpenTags();
  }

  /**
   * Writes a non-text leaf element.
   */
  protected void writeLeaf(Element e) throws IOException
  {
    // NOTE: Haven't tested if this is correct.
    if(e.getName().equals(StyleConstants.IconElementName))
      writeImage(e);
    else
      writeComponent(e);
  }

  /**
   * Write the HTML attributes which do not have tag equivalents,
   * e.g. attributes other than bold/italic/underlined.
   */
  protected void writeNonHTMLAttributes(AttributeSet attr) throws IOException
  {
    String style = "";

    // Alignment? Background?

    if( StyleConstants.getForeground(attr) != null )
      style = style + "color: " +
        getColor(StyleConstants.getForeground(attr)) + "; ";

    style = style + "font-size: "+StyleConstants.getFontSize(attr)+"pt; ";
    style = style + "font-family: "+StyleConstants.getFontFamily(attr);

    startFontTag(style);
  }

  /**
   * Write the styles used.
   */
  protected void writeStyles() throws IOException
  {
    if(doc instanceof DefaultStyledDocument)
      {
        Enumeration<?> styles = ((DefaultStyledDocument)doc).getStyleNames();
        while(styles.hasMoreElements())
          writeStyle(doc.getStyle((String)styles.nextElement()));
      }
    else
      { // What else to do here?
        Style s = doc.getStyle("default");
        if(s != null)
          writeStyle( s );
      }
  }

  /**
   * Write a set of attributes.
   */
  protected void writeAttributes(AttributeSet attr) throws IOException
  {
    Enumeration<?> attribs = attr.getAttributeNames();
    while(attribs.hasMoreElements())
      {
        Object attribName = attribs.nextElement();
        String name = attribName.toString();
        String output = getAttribute(name, attr.getAttribute(attribName));
        if( output != null )
          {
            indent();
            write( output + NEWLINE );
          }
      }
  }

  /**
   * Deliberately unimplemented, handles component elements.
   */
  protected void writeComponent(Element elem) throws IOException
  {
  }

  /**
   * Deliberately unimplemented.
   * Writes StyleConstants.IconElementName elements.
   */
  protected void writeImage(Element elem) throws IOException
  {
  }

  // -------------------- Private methods. --------------------------------

  /**
   * Write a single style attribute
   */
  private String getAttribute(String name, Object a) throws IOException
  {
    if(name.equals("foreground"))
      return "foreground:"+getColor((Color)a)+";";
    if(name.equals("background"))
      return "background:"+getColor((Color)a)+";";
    if(name.equals("italic"))
      return "italic:"+(((Boolean)a).booleanValue() ? "italic;" : ";");
    if(name.equals("bold"))
      return "bold:"+(((Boolean)a).booleanValue() ? "bold;" : "normal;");
    if(name.equals("family"))
      return "family:" + a + ";";
    if(name.equals("size"))
      {
        int size = ((Integer)a).intValue();
        int htmlSize;
        if( size > 24 )
          htmlSize = 7;
        else if( size > 18 )
          htmlSize = 6;
        else if( size > 14 )
          htmlSize = 5;
        else if( size > 12 )
          htmlSize = 4;
        else if( size > 10 )
          htmlSize = 3;
        else if( size > 8 )
          htmlSize = 2;
        else
          htmlSize = 1;

        return "size:" + htmlSize + ";";
      }

    return null;
  }

  /**
   * Stupid that Color doesn't have a method for this.
   */
  private String getColor(Color c)
  {
    String r = "00" + Integer.toHexString(c.getRed());
    r = r.substring(r.length() - 2);
    String g = "00" + Integer.toHexString(c.getGreen());
    g = g.substring(g.length() - 2);
    String b = "00" + Integer.toHexString(c.getBlue());
    b = b.substring(b.length() - 2);
    return "#" + r + g + b;
  }

  /**
   * Empty the stack of open tags
   */
  private void endOpenTags() throws IOException
  {
    while(tagStack.size() > 0)
      write(tagStack.pop());

    if( inFontTag() )
      {
        write(""+NEWLINE);
        endFontTag();
      }
  }

  /**
   * Output a single style
   */
  private void writeStyle(Style s) throws IOException
  {
    if( s == null )
      return;

    writeStartTag("p."+s.getName()+" {");
    writeAttributes(s);
    writeEndTag("}");
  }

  private boolean hasText(Element e) throws BadLocationException
  {
    return (getText(e).trim().length() > 0);
  }
}
