
package spacewar;


import java.util.Vector;
import java.util.Enumeration;
import java.awt.Graphics;
import java.awt.Color;
import java.util.Random;

/**
 * This is the standard display aspect.
 */
class Display1 extends Display {
    /*
     * Here's the color scheme for the game.  No other places in this file
     * should say Color.xxx.  Instead, that color should be given a symbolic
     * name here.
     */
    private static Color backgroundColor        = Color.black;
    private static Color player1ShipColor       = Color.white;
    private static Color player2ShipColor       = Color.gray;
    private static Color robotShipColor         = new Color(0xa00000);
    private static Color flameColor             = Color.red;
    private static Color shipExplosionColor     = Color.red;
    private static Color bulletColor            = Color.green;
    private static Color energyPacketOuterColor = Color.blue;
    private static Color energyPacketInnerColor = new Color(0x7070FF);
    private static Color statusLabelsColor      = Color.white;
    private static Color statusMeterBorderColor = Color.white;
    private static Color energyStatusMeterColor = Color.blue;
    private static Color damageStatusMeterColor = Color.red;


    Display1(Game game) {
        super(game);
        frame.setLocation(20, 20);
    }

    void noticeSizeChange() {
        super.noticeSizeChange();
        setBackground(backgroundColor);
    }

    void paintObjects(Graphics g) {
        SpaceObject[] objects = game.getRegistry().getObjects();
        final int len = objects.length;
        for (int i = 0; i < len; i++) {
            objects[i].paint(g);
        }
    }

    static aspect SpaceObjectPainting {

        abstract private void SpaceObject.paint(Graphics g);

        /*
         * Ships are by far and away the most complex of the space Objects
         * to paint.  First off, we need to set the color when the ship
         * is made.
         */
        private Color Ship.color;

        after(Pilot pilot) returning (Ship ship): call(Ship Game.newShip(Pilot)) && args(pilot) {
            if (pilot.getNumber() == 1)
                ship.color = player1ShipColor;
            else if (pilot.getNumber() == 2)
                ship.color = player2ShipColor;
            else
                ship.color = robotShipColor;
        }

        private void Ship.paint(Graphics g) {
            final double PI  = Math.PI;
            int[] radius     = {15, 12, -4, 12, -9, -15, -9};
            double[] angle   = {0, PI * 3/4, 0, -PI * 3/4, PI/8, 0, -PI/8};
            int[] x;
            int[] y;

            Random  random = new Random();

            if (this.getDamage() >= this.MAX_DAMAGE) {
                int lines = 20;
                x = new int[lines];
                y = new int[lines];
                g.setColor(shipExplosionColor);
                for (int i = 0; i < lines; i++) {
                    x[i] = (int)(this.getXPos()) + random.nextInt() % 20;
                    y[i] = (int)(this.getYPos()) + random.nextInt() % 20;
                }
                for (int i = 0; i < lines; i++)
                    g.drawLine(x[i], y[i], x[(i + 1) % lines], y[(i + 1) % lines]);
            } else {
                x = new int[7];
                y = new int[7];

                g.setColor(this.color);

                radius[5] += random.nextInt() % 3;
                // convert coordinates from polar to cartesian
                for (int i = 0; i < 7; i++) {
                    x[i] = (int)
                        (this.getXPos() +
                         Math.cos(this.getOrientation() + angle[i]) * radius[i]);
                    y[i] = (int)
                        (this.getYPos() +
                         Math.sin(this.getOrientation() + angle[i]) * radius[i]);
                }

                // draw the body as a polygon
                g.drawPolygon(x, y, 4);

                // if the ship is accelerating, draw in a flame
                if (this.getRAcc() != 0) {
                    g.setColor(flameColor);
                    g.drawLine(x[4], y[4], x[5], y[5]);
                    g.drawLine(x[5], y[5], x[6], y[6]);
                }
            }
        }

        /*
         * Bullets
         */
        private void Bullet.paint(Graphics g) {
            g.setColor(bulletColor);
            g.fillOval((int)this.getXPos() - 1,
                       (int)this.getYPos() - 1,
                       3,
                       3);
        }

        /*
         * energy packets
         */
        private void EnergyPacket.paint(Graphics g) {
            g.setColor(energyPacketOuterColor);
            g.fillOval((int)this.getXPos() - 5,
                       (int)this.getYPos() - 5,
                       10, 10);
            g.setColor(energyPacketInnerColor);
            g.fillOval((int)this.getXPos() - 2,
                       (int)this.getYPos() - 2,
                       3, 3);
        }
    }


    void paintStatus(Graphics g) {
        int left1 = 60;
        int top1  = 0;

        int left2 = 200;
        int top2  = 0;

        g.setColor(statusLabelsColor);
        g.drawString("energy:", 5, top1 + 15);
        g.drawString("damage:", 5, top1 + 30);

        if (getPilot1() != null)
            paintLevels(g, getPilot1().getShip(), top1, left1);
        if (getPilot2() != null)
            paintLevels(g, getPilot2().getShip(), top2, left2);
    }

    static void paintLevels(Graphics g, Ship ship, int top, int left) {
        if (ship == null)
            return;
        else if (ship.isAlive()) {
            g.setColor(statusMeterBorderColor);
            g.drawRect(left, top + 6,  101, 10);
            g.drawRect(left, top + 21, 101, 10);
            g.setColor(energyStatusMeterColor);
            g.fillRect(left + 1, top + 7,  (int)(ship.getEnergyLevel()*100), 9);
            g.setColor(damageStatusMeterColor);
            g.fillRect(left + 1, top + 22, (int)(ship.getDamageLevel()*100), 9);
        }
        else {
            g.setColor(damageStatusMeterColor);
            g.drawString("Ship is destroyed", left+1, top+15);
        }
    }
}
