package demo;

import java.awt.*;
import java.awt.event.*;
import java.util.*;
import javax.media.opengl.*;
import jocode.*;
import jomodel.*;

/**
 * Render 2D text using texture mapping.  Text is drawn over a simple 3D
 * scene and is incorporated into the scene as a texture on an object.
 * <P>
 * The GLApp.buildfont() function creates a character set by texture-mapping
 * images of characters onto quads.
 * <P>
 * GLApp.print(String) renders text strings as a series of texture-mapped quads.
 * <P>
 * The GLFont class takes a similar approach, but builds a character set
 * dynamically using the Java Font class.  Character images can drawn using
 * any font that your system supports, with italics, bold, and in a wide
 * ranges of sizes.
 * <P>
 * GLApp initializes the LWJGL environment for OpenGL rendering,
 * ie. creates a window, sets the display mode, inits mouse and keyboard,
 * then runs a loop that calls draw().
 * <P>
 * Special thanks to NeHe and Giuseppe D'Agata for the "2D Texture Font"
 * tutorial (http://nehe.gamedev.net).
 * <P>
 * napier at potatoland dot org
 */
public class DemoText extends JOApp {
    // Light position: if last value is 0, then this describes light direction.  If 1, then light position.
    float lightPosition[]= { 0f, 2f, 2f, 0f };

    // sphere displaylist
    int sphereDL;

    // holds a texture mapped font
    JOFont font;

    // will hold the last seven characters types
    LinkedList<String> toAdd = new LinkedList<String>();
    ArrayList<Integer> lastchars = new ArrayList<Integer>();

	/**
	 * Start the application.  demo.run() calls setup(), handles mouse and keyboard input,
	 * and calls draw() in a loop.
	 */
    public static void main(String args[]) {
        DemoText demo = new DemoText();
        windowTitle   = "GLApp Text Demo";
        displayWidth  = 800;
        displayHeight = 600;
        demo.run();
    }

    /**
     * Initialize the scene.  Called by GLApp.run()
     */
    @Override
    public void setup() {
        // setup and enable perspective
        setPerspective();

        // Create a white light
        setLight(GL.GL_LIGHT1,
        		 new float[] { 1f,  1f,  1f,  1f },  // diffuse
        		 new float[] { .8f, .8f, .8f, 1f },  // ambient
        		 new float[] { 1f,  1f,  1f,  1f },  // specular
        		 lightPosition );

        // off-white material, very shiny
        setMaterial(new float[] {.6f,.6f,.45f,1}, 1f);

        // lighten up the shadows a bit
        setAmbientLight(new float[] {.35f, .45f, .5f, 1f});

        // make a sphere display list
        sphereDL = beginDisplayList(); {
        	renderSphere();
        }
        endDisplayList();

        // Make a font object to render text
		font = new JOFont( new Font("Trebuchet", Font.BOLD, 18) );
    }

    /**
     * set the field of view and view depth.
     */
    public void setPerspective() {
    	setPerspective(40f, .1f, 500f);
    }

    /**
     * Render one frame.  Called by GLApp.run().
     */
    @Override
    public void draw() {
        // clear depth buffer and color
        gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT);

        // select model view for subsequent transforms
        gl.glMatrixMode(GL.GL_MODELVIEW);
        gl.glLoadIdentity();

        // do gluLookAt() with viewpoint position, direction, orientation
        glu.gluLookAt(0f, -3f, 33f, // where is the eye
        			0f, -3f, 0f,    // what point are we looking at
        			0f, 1f, 0f);   // which way is up
        
        // create any new characters that were typed
        for (String c : toAdd) createChar(c);
        toAdd.clear();

        // draw the scene (after we draw the shadows, so everything layers correctly)
        drawSpheres();

        // Place the light.  Light will move with the rest of the scene
        setLightPosition(GL.GL_LIGHT1, lightPosition);

        // render some text using a font
		font.print(40, viewportH-100, "Type something:");

		// render some text using texture-mapped font
		print( 40, 210, "Text rendered with the default JOApp.print() function uses");
        print( 40, 190, "a texture mapped fixed width font, loaded from an image file.");

        // render some text using the GLFont class
        font.print( 40,125, "Text rendered with the GLFont class generates a proportional spaced");
        font.print( 40,100, "character set from a Java Font object.");
    }
    
    public void createChar(String c) {
        // pick a font:
        //Font font = new Font("Times New Roman", Font.BOLD, 120);
        //Font font = new Font("Comic Sans MS", Font.BOLD, 120);
        Font font = new Font("Courier New", Font.BOLD, 120);

        // make a texture image of the character
        int textureHandle = JOFont.makeCharTexture(font, c, JOMaterial.colorBlack, JOMaterial.colorWhite);
        lastchars.add(textureHandle);
        if (lastchars.size() > 7) {
            int oldTxtr = lastchars.get(0);
            deleteTexture(oldTxtr);
            lastchars.remove(0);
        }
    }

    public void drawSpheres() {
    	int leftpos = -12;
    	int texture = 0;
    	gl.glEnable(GL.GL_LIGHTING);
    	for (int i=0; i < 7; i++) {
    		texture = 0;
    		if (lastchars.size() > i) {
    			texture = ((Integer)lastchars.get(i)).intValue();
    		}
			gl.glBindTexture(GL.GL_TEXTURE_2D, texture);
    		gl.glPushMatrix();
    		{
    			gl.glTranslatef(leftpos, 0, 0); // move
    			gl.glScalef(2f, 2f, 2f);        // scale up
    			callDisplayList(sphereDL);
    		}
    		gl.glPopMatrix();
    		leftpos += 4;
    	}
    }

    /**
     * Use JOFont to make texture images of the last 7 characters typed
     */
    @Override
    public void keyPressed(KeyEvent e) {
        super.keyPressed(e);
        
        if (e.getKeyChar() >= 32) {   // only printable characters
            toAdd.add(String.valueOf(e.getKeyChar()));
    	}
    }
}