import com.nttdocomo.ui.*;
import com.nttdocomo.io.*;
import com.nttdocomo.util.*;

import java.util.Random;

import com.beartronics.FP;

/**
 *
 * Test Fixed Point math functions
 *
 * (C) 2001 Beartronics 
 * Author: Henry Minsky (hqm@alum.mit.edu)
 *
 * Licensed under terms "Artistic License"
 * http://www.opensource.org/licenses/artistic-license.html
 *
 */

public class MathTest extends IApplication  implements Runnable {
    MathCanvas c;
    public void start() {
	c = new MathCanvas(this);
	Display.setCurrent(c);
        Thread runner = new Thread(this);
        runner.start();
    }


    public void run() {
	c.count =0;
	c.state = c.TEST7;
        for (;;) {
            try {
                Thread.sleep(10);
            } catch (Exception e) {}

            c.repaint();

	    switch (c.state) {
	    case c.TEST1:
		if (c.count == 180) {
		    c.radius = c.getWidth() /2;
		    c.state = c.TEST2;
		}
		break;
	    case c.TEST3:
		if (c.radius < 2) {
		    c.radius = c.getWidth() /2;
		    c.state = c.TEST4;
		}
		break;
	    case c.TEST5:
		if (c.radius < 2) {
		    c.radius = c.getWidth() /2;
		    c.state = c.TEST6;
		}
		break;
	    case c.TEST7:
		c.count = 0;
		break;
	    case c.TEST8:
		c.count = 0;
		c.state = c.TEST1;
		break;
	    }

	    c.count++;
        }
    }
}

class MathCanvas extends Canvas {
    private IApplication app;

    public int count = 0;

    public static final int TEST0 = 0;
    public static final int TEST1 = 1;
    public static final int TEST2 = 2;
    public static final int TEST3 = 3;
    public static final int TEST4 = 4;
    public static final int TEST5 = 5;
    public static final int TEST6 = 6;
    public static final int TEST7 = 7;
    public static final int TEST8 = 8;

    int x1, y1, x2, y2;

    public int state = TEST0;
    int screenWidth;
    int screenHeight;

    Random rand;

    MathCanvas(IApplication app) {
	screenWidth = getWidth();
	screenHeight = getHeight();

	x1 = screenWidth / 2;
	y1 = screenHeight / 2;
	x2 = x1; 
	y2 = y1;

	this.app = app;
        setSoftLabel(Frame.SOFT_KEY_1, "Exit");
	rand = new Random();
    }

    public int radius = 0;

    void drawCircles (Graphics g) {

	int n = 360 / 5;
	int xpts[] = new int[n+1];
	int ypts[] = new int[n+1];

	int xc = screenWidth / 2;
	int yc = screenHeight / 2;

	int k = 0;
	for (int a = 0; a < 360; a+=5) {
	    int z = a * FP.PI;
	    int alpha = FP.Div(z,(180<<16));
	    int dx = FP.Cos(alpha) * radius;
	    int dy = FP.Sin(alpha) * radius;
	    xpts[k] = xc + (dx>>16);
	    ypts[k] = yc + (dy>>16);
	    k++;
	}
	g.setColor(g.getColorOfRGB(0,0,0));
	g.fillRect(0, 0, screenWidth, screenHeight);
	g.setColor(g.getColorOfRGB(0xff,0xff,0xff));
	g.drawString("hqm@ai.mit.edu",2,12);
	if (state == TEST3) {
	    g.fillPolygon(xpts, ypts, k);
	} else {
	    g.drawPolyline(xpts, ypts, k);
	}
    }

    int wrap (int val, int bound) {
	if (val < 0) {
	    return bound;
	} else if (val > bound) {
	    return 0; 
	} else {
	    return val;
	}
    }

    public void processEvent(int eventType, int param) {
	if (Display.KEY_PRESSED_EVENT == eventType) {
	    switch (param) {
	    case Display.KEY_SELECT:
	    case Display.KEY_1:
		// select next test
		state++;
		break;
	    case Display.KEY_SOFT1:
                app.terminate();
		break;
	    }
	}
    }

    boolean clearScreen = true;

    void clearScreen (Graphics g) {
	g.setColor(g.getColorOfRGB(0,0,0));
	g.fillRect(0, 0, screenWidth, screenHeight);
    }

    void paintTest1 (Graphics g) {
	if (clearScreen) {
	    clearScreen(g);
	    clearScreen = false;
	}
	// Draw a rotating line about the center of the screen
	int angle = (count<<1 % 360);
	int k = angle * FP.PI;
	int alpha = FP.Div(k,(180<<16));
	int dx = FP.Cos(alpha) * (screenWidth/2);
	int dy = FP.Sin(alpha) * (screenWidth/2);
	x2 = x1 + (dx>>16);
	y2 = y1 + (dy>>16);
	g.setColor(g.getColorOfRGB(0xff,0,0));
	g.drawLine(x1, y1, x2, y2);
    }

    void paintTest2 (Graphics g) {
	if (clearScreen) {
	    clearScreen(g);
	    clearScreen = false;
	}
	drawCircles(g);
    }


    int avx1 = 2;
    int avy1 = 3;
    int avx2 = -1;
    int avy2 = -2;

    int bvx1 = -3;
    int bvy1 = 3;
    int bvx2 = 4;
    int bvy2 = -2;

    int ax1, ay1, ax2, ay2;
    int bx1, by1, bx2, by2;

    // test line intersection code
    void paintTest3 (Graphics g) {
	clearScreen(g);

	// Draw a rotating line about the center of the screen
	// endpoints for line intersection test
	ax1 = wrap(ax1 + avx1, screenWidth);
	ay1 = wrap(ay1 + avy1, screenHeight);
	ax2 = wrap(ax2 + avx2, screenWidth);
	ay2 = wrap(ay2 + avy2, screenHeight);


	bx1 = wrap(bx1 + bvx1, screenWidth);
	by1 = wrap(by1 + bvy1, screenHeight);
	bx2 = wrap(bx2 + bvx2, screenWidth);
	by2 = wrap(by2 + bvy2, screenHeight);

	boolean crosses = FP.intersects (ax1, ay1, ax2, ay2, 
				      bx1, by1, bx2, by2);


	g.setColor(g.getColorOfRGB(0xff,0,0xff));
	g.drawLine(ax1, ay1, ax2, ay2);
	g.setColor(g.getColorOfRGB(0,0xff,0xff));
	g.drawLine(bx1, by1, bx2, by2);

	if (crosses) {
	    g.setColor(g.getColorOfRGB(0xff,0,0));
	    g.fillRect((FP.xIntersect>>16)-1, (FP.yIntersect>>16)-1, 3, 3);
	}

    }



    public void paint(Graphics g) {
	g.lock();
	switch (state) {
	case TEST1: 
	    paintTest1(g);
	    break;
	case TEST2: 
	    break;
	case TEST3: 
	    radius--;
	    paintTest2(g);
	    break;
	case TEST4: 
	    clearScreen = true;
	    break;
	case TEST5: 
	    radius--;
	    paintTest2(g);
	    break;
	case TEST7: 
	    paintTest3(g);
	    break;
	}
	g.unlock(true);
   }

}