/*
 * WheelsApplet.java
 *
 * (C) 2005, Alex S.
 */

import java.awt.*;
import java.util.Vector;

/**
 * Wheels thingie
 */
public class WheelsApplet extends BufferedApplet {

    double x,y;
    double carangle;
    double turnangle;
    pMatrix m;

    double model_scale = 30;
    int mouse_x,mouse_y;

    /**
     * initialize things
     */
    public void init(){
        super.init();
        m = new pMatrix();
        x = bounds().width / 2;
        y = -bounds().height / 2;
        carangle = Math.PI/2;
        turnangle = 0;
        mouse_x = mouse_y = 0;
    }

    private void drawUnitBox(Graphics g,Color col){
        double[] a = {-1,1,0,1};
        double[] b = {1,1,0,1};
        double[] c = {1,-1,0,1};
        double[] d = {-1,-1,0,1};
        a = m.mult(a);
        b = m.mult(b);
        c = m.mult(c);
        d = m.mult(d);
        g.setColor(col);
        int[] xs = { (int)a[0],(int)b[0],(int)c[0],(int)d[0] };
        int[] ys = { (int)a[1],(int)b[1],(int)c[1],(int)d[1] };
        g.fillPolygon(xs,ys,4);
        g.setColor(Color.black);
        g.drawPolygon(xs,ys,4);
    }

    /**
     * function that gets called whenever something needs to be
     * rendered.
     */
    public void render(Graphics g) {
        double ta,sintheta;
        
        double carLen = 2.5;    // middle of car

        double carWidth = 4;

        double flw,frw,blw,brw; // wheel angles



        if (damage) {

            flw = frw = blw = brw = turnangle;

            sintheta = Math.sin(turnangle);
            if(sintheta > 0){
                double E = carLen * Math.cos(turnangle) / sintheta + carWidth;
                frw = Math.atan2(carLen,E);
                flw = turnangle;
                brw = -frw;
                blw = -flw;

                // note: if carLen isn't in the center (front/back wheels
                // aren't capable of the same angles), then a similar calculation
                // can be done for back wheels. carLen is used as a 'distance'
                // of wheel axile from the center of the car.

            }else if(sintheta < 0){
                double E = carLen * Math.cos(turnangle) / -sintheta + carWidth;
                frw = turnangle;
                flw = -Math.atan2(carLen,E);
                brw = -frw;
                blw = -flw;
            }

            g.setColor(Color.lightGray);
            g.fillRect(0, 0, bounds().width, bounds().height);
            g.setColor(Color.black);

            m.push();
            m.reflecty();
            m.translate(x,y,0);
            m.rotatez(carangle);
            m.scale(model_scale);

            m.push();
            m.scale(3,2,0);
            drawUnitBox(g,Color.red);
            m.pop();

            // right front wheel
            m.push();
            m.translate(2.5,-2,0);
            m.rotatez(frw);
            m.scale(0.4,0.15,0);
            drawUnitBox(g,Color.blue);
            m.scale(0.0001,1000,0);
            drawUnitBox(g,Color.black);
            m.pop();

            // left front wheel
            m.push();
            m.translate(2.5,2,0);
            m.rotatez(flw);
            m.scale(0.4,0.15,0);
            drawUnitBox(g,Color.blue);
            m.scale(0.0001,1000,0);
            drawUnitBox(g,Color.black);
            m.pop();

            // right back wheel
            m.push();
            m.translate(-2.5,-2,0);
            m.rotatez(brw);
            m.scale(0.4,0.15,0);
            drawUnitBox(g,Color.blue);
            m.scale(0.0001,1000,0);
            drawUnitBox(g,Color.black);
            m.pop();

            // left back wheel
            m.push();
            m.translate(-2.5,2,0);
            m.rotatez(blw);
            m.scale(0.4,0.15,0);
            drawUnitBox(g,Color.blue);
            m.scale(0.0001,1000,0);
            drawUnitBox(g,Color.black);
            m.pop();

            m.pop();

        }
    }

    public boolean mouseDown(Event evt, int x, int y){
        mouse_x = x;
        mouse_y = y;
        return true;
    }
    public boolean mouseUp(Event evt, int x, int y){
        return true;
    }
    public boolean mouseDrag(Event evt, int x, int y){
        int dx = x - mouse_x;
        int dy = y - mouse_y;

        model_scale += dy * 0.02;
        if(model_scale < 4)
            model_scale = 4;
        if(model_scale > 50)
            model_scale = 50;

        turnangle += dx * 0.001;
        if(turnangle < -Math.PI/2+0.4)
            turnangle = -Math.PI/2+0.4;
        if(turnangle > Math.PI/2-0.4)
            turnangle = Math.PI/2-0.4;

        damage = true;
        return true;
    }
    public boolean keyUp(Event evt, int key){
        if(key == Event.LEFT && turnangle < Math.PI/2-0.4){
            turnangle += Math.PI/32;
        }else if(key == Event.RIGHT && turnangle > -Math.PI/2+0.4){
            turnangle -= Math.PI/32;
        }
        damage=true;
        return true;
    }
    public boolean keyDown(Event evt, int key){
        return true;
    }
}

