/**
 * @(#)MinoidsPanel.java
 * @author JLMJ
 * @date 2001-10-03
 */
package minoids1.viewer;

import minoids1.Minoid;

import java.awt.*;
import java.awt.event.*;
import java.util.*;
import java.applet.Applet;

public class MinoidsViewerPanel extends Panel
{
    private int minoidsShown = 0;
    private int scale = 4;
    private int xOffset;
    private int yOffset;

    private static final int[] xy = new int[] {1, -3, 5, 1, -1, 3, -5, -1 };
    private static final int[] xz = new int[] {2, -1, 2, 5, -2, 1, -2, -5 };
    private static final int[] yz = new int[] {3, 2, -3, 4, -3, -2, 3, -4 };

    private Vector vector = new Vector();
    private Graphics offGraphics;
    private Image offScreen;
    private Dimension offScreenDimension;
    
    private Color color1 = Color.cyan.darker().darker();
    private Color color2 = Color.cyan.darker();
    private Color color3 = Color.cyan;

    private PopupMenu optionsPopupMenu;
    
    public MinoidsViewerPanel(PopupMenu optionsPopupMenu) {
        this.enableEvents(AWTEvent.MOUSE_EVENT_MASK);
        this.enableEvents(AWTEvent.MOUSE_MOTION_EVENT_MASK);
        this.optionsPopupMenu = optionsPopupMenu;
        if (optionsPopupMenu != null)
            this.add(optionsPopupMenu);
    }
    
    public void processMouseEvent(MouseEvent event) {
        if (event.isPopupTrigger()) {
            if (optionsPopupMenu != null)
                optionsPopupMenu.show(this, event.getX(), event.getY());
        } else {
            super.processMouseEvent(event);
        }
    }

    public void paint(Graphics g) {
        Dimension d = getSize();
        xOffset = d.width / 2;
        yOffset = d.height / 2;
        if (offScreen == null) {
            offScreen = createImage(d.width, d.height);
            offScreenDimension = d;
        }
        offGraphics = offScreen.getGraphics();
        offGraphics.setColor(getBackground());
        offGraphics.fillRect(0, 0, d.width, d.height);

        drawAxis(g, 8);
        int count = 0;
        int x, y, z;
        for (int i=0; i < vector.size(); i++) {
            Minoid m = (Minoid)vector.elementAt(i);
            if (!m.isVisible())
                continue;
            x = m.getX(); y = m.getY(); z = m.getZ();
            Polygon p = getPolygon(x, y, z);
            offGraphics.setColor(
                (x & 1) == 0 ? color1 :
                (y & 1) == 0 ? color2 : color3);
            offGraphics.fillPolygon(p);
            offGraphics.setColor(Color.black);
            offGraphics.drawPolygon(p);
            count++;
        }
        offGraphics.drawString(count + " minoids shown", 20, 20);
        offGraphics.drawImage(offScreen, 0, 0, null);
        g.drawImage(offScreen, 0, 0, null);
    }

    private void drawAxis(Graphics g, int ext) {
        offGraphics.setColor(Color.black);
        int x2, y2;
        // x axis
        int x1 = xOffset; int y1 = yOffset;
        x2 = 4*ext*scale + xOffset;
        y2 = 4*ext*scale + yOffset;
        offGraphics.drawLine(x1, y1, x2, y2);
        x2 = -6*ext*scale + xOffset;
        y2 = 2*ext*scale + yOffset;
        offGraphics.drawLine(x1, y1, x2, y2);
        x2 = 0*ext*scale + xOffset;
        y2 = -6*ext*scale + yOffset;
        offGraphics.drawLine(x1, y1, x2, y2);
    }
    
    public void update(Graphics g) {
        paint(g);
    }

    public void add(Minoid n) {
        for (int j=0; j < vector.size(); j++) {
            Minoid m = (Minoid)vector.elementAt(j);
            int mi = (m.getX() << 16) + (m.getY() << 8) + m.getZ();
            int ni = (n.getX() << 16) + (n.getY() << 8) + n.getZ();
            if (mi == ni)
                return;
            else if (mi > ni) {
                vector.insertElementAt(n, j);
                return;
            }
        }
        vector.insertElementAt(n, vector.size());
    }
    
    public void add(Minoid[] minoids) {
        if (minoids != null)
            for (int i=0; i < minoids.length; i++)
                add(minoids[i]);
    }
    
    public void remove(Minoid n) {
        for (int i=0; i < vector.size(); i++) {
            Minoid m = (Minoid)vector.elementAt(i);
            if (m == n) {
                vector.remove(n);
            }
        }
    }

    public void removeAllMinoids() {
        vector.removeAllElements();
        repaint();
    }
    
    private Polygon getPolygon(int x, int y, int z) {
        int px = x & 1;
        int py = y & 1;
        int pz = z & 1;
        int ox = 2*x - 3*y;
        int oy = 2*x + 1*y - 3*z;
        if (px == 1 && py == 1 && pz == 0)
            return getPolygon(ox, oy, xy);
        else if (px == 1 && py == 0 && pz == 1)
            return getPolygon(ox, oy, xz);
        else if (px == 0 && py == 1 && pz == 1)
            return getPolygon(ox, oy, yz);
        else
            return null;
    }

    private Polygon getPolygon(int ox, int oy, int[] coordinates) {
        int[] xs = new int[4];
        int[] ys = new int[4];
        for (int i=0; i < coordinates.length; i += 2) {
            xs[i/2] = (coordinates[i] + ox)*scale + xOffset;
            ys[i/2] = (coordinates[i+1] + oy)*scale + yOffset;
        }
        return new Polygon(xs, ys, 4);
    }
}
    

