/*
 * @(#)SceneElement.java	1.8 98/10/26
 *
 * Copyright (c) 1998 Sun Microsystems, Inc. All Rights Reserved.
 *
 * Sun grants you ("Licensee") a non-exclusive, royalty free, license to use,
 * modify and redistribute this software in source and binary code form,
 * provided that i) this copyright notice and license appear on all copies of
 * the software; and ii) Licensee does not utilize the software in a manner
 * which is disparaging to Sun.
 *
 * This software is provided "AS IS," without a warranty of any kind. ALL
 * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING ANY
 * IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR
 * NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN AND ITS LICENSORS SHALL NOT BE
 * LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
 * OR DISTRIBUTING THE SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR ITS
 * LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT,
 * INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER
 * CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF
 * OR INABILITY TO USE SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGES.
 *
 * This software is not designed or intended for use in on-line control of
 * aircraft, air traffic, aircraft navigation or aircraft communications; or in
 * the design, construction, operation or maintenance of any nuclear
 * facility. Licensee represents and warrants that it will not use or
 * redistribute the Software for such purposes.
 */

package project;

import java.io.IOException;
import java.io.Writer;

import javax.swing.JEditorPane;

import org.w3c.dom.Node;

import com.sun.xml.tree.*;


public class SceneElement extends TitledElement
{
    private JEditorPane	text;

    public SceneElement () { }

    //
    // Override swing.TreeNode methods to say this is a leaf.
    //
    // For display purposes it is ... the scenes should be
    // displayed specially, perhaps using an editor kit
    //
    public boolean getAllowsChildren () { return false; }
    public boolean isLeaf () { return true; }

    //
    // Remember where we'll draw ourselves
    //
    public void setEditor (JEditorPane editor)
	{ text = editor; }
    
    //
    // Draw ourselves!  Not intended to be efficient; this
    // is very much a quick'n'dirty job.
    //
    public void draw ()
    {
	if (text != null)
	    text.setText (toHtml32Text ());
    }

    //
    // Quick'n'Dirty display:  convert self to HTML 3.2, for
    // later rendering using Swing's HTML "editor" kit.  This
    // is one place that an XSL engine could be used to much
    // better effect ... both more flexible, and more complete.
    //
    // This has a somewhat expensive optimization:  saving the
    // string.  It's expensive in that each of 5-20 scenes is
    // saved.
    //
    private String	savedString;

    public String toHtml32Text ()
    {
	if (savedString != null)
	    return savedString;

    	StringBuffer	buf = new StringBuffer (40000);
    	Node		current = getFirstChild ();
    	Node		next;
    	String		etag = null;
    	String		value;

	buf.append ("<HTML><HEAD><TITLE></TITLE></HEAD><BODY>\n");

	// XXX put act and play titles here too...

	buf.append ("<CENTER><H3 color=maroon>");
	buf.append (getTitle ());
	buf.append ("</H3></CENTER>\n");

    	while (current != this) {
	    switch (current.getNodeType ()) {
	      case Node.ELEMENT_NODE:
		//
		// <!ELEMENT TITLE    (#PCDATA)>
		// <!ELEMENT SCENE
		//	(TITLE, SUBTITLE*, (SPEECH | STAGEDIR | SUBHEAD)+)>
		// <!ELEMENT SPEECH
		//	(SPEAKER+, (LINE | STAGEDIR | SUBHEAD)+)>
		// <!ELEMENT SPEAKER  (#PCDATA)>
		// <!ELEMENT LINE     (#PCDATA | STAGEDIR)*>
		// <!ELEMENT STAGEDIR (#PCDATA)>
		// <!ELEMENT SUBTITLE (#PCDATA)>
		// <!ELEMENT SUBHEAD  (#PCDATA)>
		//
		// tests ordered by frequency of occurence, for speed;
		// titles have already been removed.
		//
		value = current.getNodeName ();
		next = null;
		if ("LINE".equals (value)) {
		    ((ElementNode)current).normalize ();

		    //
		    // XXX this breaks with embedded STAGEDIRs ...
		    //

    		    buf.append (current.getFirstChild ().getNodeValue ());
    		    buf.append ("<br>");
		    next = current.getNextSibling ();
		} else if ("SPEAKER".equals (value))
		    //next = wrap (buf, current, "FONT", "color=olive");
		    next = wrap (buf, current, "B", null);
		else if ("SPEECH".equals (value))
		    next = current.getFirstChild ();
		else if ("STAGEDIR".equals (value))
		    next = center (buf, current, "EM", null);
		else if ("SUBTITLE".equals (value))
		    next = center (buf, current, "H4", "color=maroon");
		else if ("SUBHEAD".equals (value))
		    next = center (buf, current, "H5", "color=maroon");
		// else error, ignore
		buf.append ('\n');

	        if (next == null) do {
		    current = current.getParentNode ();
		    next = current.getNextSibling ();
		} while (next == null && current != this);
		current = next;
		// FALLTHROUGH

	      default:
		continue;
	    }
	}
	buf.append ("</BODY></HTML>");
	savedString = buf.toString ();
	return savedString;
    }

    private Node center (
    	StringBuffer	buf,
    	Node		element,
    	String		htmlTag,
    	String		htmlAttributes
    ) {
    	buf.append ("<CENTER>");
    	Node retval = wrap (buf, element, htmlTag, htmlAttributes);
    	buf.append ("</CENTER>");
    	return retval;
    }

    private Node wrap (
    	StringBuffer	buf,
    	Node		element,
    	String		htmlTag,
    	String		htmlAttributes
    ) {
    	buf.append ('<');
    	buf.append (htmlTag);
    	if (htmlAttributes != null) {
    	    buf.append (' ');
    	    buf.append (htmlAttributes);
    	}
    	buf.append ('>');
    	// element normalized to one child, a text node
    	buf.append (element.getFirstChild ().getNodeValue ());
    	buf.append ("</");
    	buf.append (htmlTag);
    	buf.append (">\n");

    	while (element.getNextSibling () == null) {
    	    element = element.getParentNode ();
    	    if (element == this)
    	        return this;
    	}
    	return element.getNextSibling ();
    }
}
