/*
 * Copyright 1997-2006 Sun Microsystems, Inc.  All Rights Reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   - Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   - Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *
 *   - Neither the name of Sun Microsystems nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

/*
 */

import java.applet.Applet;
import java.awt.event.*;
import java.awt.*;
import java.awt.image.ColorModel;
import java.awt.image.MemoryImageSource;

public class DitherTest extends Applet implements Runnable {
    final private static int NOOP = 0;
    final private static int RED = 1;
    final private static int GREEN = 2;
    final private static int BLUE = 3;
    final private static int ALPHA = 4;
    final private static int SATURATION = 5;

    private Thread runner;

    private DitherControls XControls;
    private DitherControls YControls;
    private DitherCanvas canvas;

    public static void main(String args[]) {
        Frame f = new Frame("DitherTest");
        DitherTest ditherTest = new DitherTest();
        ditherTest.init();
        f.add("Center", ditherTest);
        f.pack();
        f.setVisible(true);
        ditherTest.start();
    }

    public void init() {
        String xspec = null, yspec = null;
        int xvals[] = new int[2];
        int yvals[] = new int[2];

        try {
            xspec = getParameter("xaxis");
            yspec = getParameter("yaxis");
        } catch (NullPointerException npe) {
            //only occurs if run as application
        }

        if (xspec == null) {
            xspec = "red";
        }
        if (yspec == null) {
            yspec = "blue";
        }
        int xmethod = colormethod(xspec, xvals);
        int ymethod = colormethod(yspec, yvals);

        setLayout(new BorderLayout());
        XControls = new DitherControls(this, xvals[0], xvals[1],
                                       xmethod, false);
        YControls = new DitherControls(this, yvals[0], yvals[1],
                                       ymethod, true);
        YControls.addRenderButton();
        add("North", XControls);
        add("South", YControls);
        add("Center", canvas = new DitherCanvas());
    }

    private int colormethod(String s, int vals[]) {
        int method = NOOP;
        if (s == null) {
            s = "";
        }
        String lower = s.toLowerCase();
        int len = 0;
        if (lower.startsWith("red")) {
            method = RED;
            lower = lower.substring(3);
        } else if (lower.startsWith("green")) {
            method = GREEN;
            lower = lower.substring(5);
        } else if (lower.startsWith("blue")) {
            method = BLUE;
            lower = lower.substring(4);
        } else if (lower.startsWith("alpha")) {
            method = ALPHA;
            lower = lower.substring(5);
        } else if (lower.startsWith("saturation")) {
            method = SATURATION;
            lower = lower.substring(10);
        }
        if (method == NOOP) {
            vals[0] = 0;
            vals[1] = 0;
            return method;
        }
        int begval = 0;
        int endval = 255;
        try {
            int dash = lower.indexOf('-');
            if (dash < 0) {
                endval = Integer.parseInt(lower);
            } else {
                begval = Integer.parseInt(lower.substring(0, dash));
                endval = Integer.parseInt(lower.substring(dash + 1));
            }
        } catch (NumberFormatException nfe) {
        }

        if (begval < 0) {
            begval = 0;
        } else if (begval > 255) {
            begval = 255;
        }

        if (endval < 0) {
            endval = 0;
        } else if (endval > 255) {
            endval = 255;
        }

        vals[0] = begval;
        vals[1] = endval;
        return method;
    }

    /**
     * Calculates and returns the image.  Halts the calculation and returns
     * null if the Applet is stopped during the calculation.
     */
    private Image calculateImage() {
        Thread me = Thread.currentThread();

        int width = canvas.getSize().width;
        int height = canvas.getSize().height;
        int xvals[] = new int[2];
        int yvals[] = new int[2];
        int xmethod = XControls.getParams(xvals);
        int ymethod = YControls.getParams(yvals);
        int pixels[] = new int[width * height];
        int c[] = new int[4];   //temporarily holds R,G,B,A information
        int index = 0;
        for (int j = 0; j < height; j++) {
            for (int i = 0; i < width; i++) {
                c[0] = c[1] = c[2] = 0;
                c[3] = 255;
                if (xmethod < ymethod) {
                    applymethod(c, xmethod, i, width, xvals);
                    applymethod(c, ymethod, j, height, yvals);
                } else {
                    applymethod(c, ymethod, j, height, yvals);
                    applymethod(c, xmethod, i, width, xvals);
                }
                pixels[index++] = ((c[3] << 24) |
                                   (c[0] << 16) |
                                   (c[1] << 8) |
                                   c[2]);
            }

            // Poll once per row to see if we've been told to stop.
            if (runner != me) {
                return null;
            }
        }
        return createImage(new MemoryImageSource(width, height,
                            ColorModel.getRGBdefault(), pixels, 0, width));
    }

    private void applymethod(int c[], int method, int step,
                             int total, int vals[]) {
        if (method == NOOP) {
            return;
        }
        int val = ((total < 2)
                   ? vals[0]
                   : vals[0] + ((vals[1] - vals[0]) * step / (total - 1)));
        switch (method) {
        case RED:
            c[0] = val;
            break;
        case GREEN:
            c[1] = val;
            break;
        case BLUE:
            c[2] = val;
            break;
        case ALPHA:
            c[3] = val;
            break;
        case SATURATION:
            int max = Math.max(Math.max(c[0], c[1]), c[2]);
            int min = max * (255 - val) / 255;
            if (c[0] == 0) {
                c[0] = min;
            }
            if (c[1] == 0) {
                c[1] = min;
            }
            if (c[2] == 0) {
                c[2] = min;
            }
            break;
        }
    }

    public void start() {
        runner = new Thread(this);
        runner.start();
    }

    public void run() {
        canvas.setImage(null);  // Wipe previous image
        Image img = calculateImage();
        if (img != null && runner == Thread.currentThread()) {
            canvas.setImage(img);
        }
    }

    public void stop() {
        runner = null;
    }

    public void destroy() {
        remove(XControls);
        remove(YControls);
        remove(canvas);
    }

    public String getAppletInfo() {
        return "An interactive demonstration of dithering.";
    }

    public String[][] getParameterInfo() {
        String[][] info = {
            {"xaxis", "{RED, GREEN, BLUE, ALPHA, SATURATION}",
             "The color of the Y axis.  Default is RED."},
            {"yaxis", "{RED, GREEN, BLUE, ALPHA, SATURATION}",
             "The color of the X axis.  Default is BLUE."}
        };
        return info;
    }
}

class DitherCanvas extends Canvas {
    private Image img;
    private static String calcString = "Calculating...";

    public void paint(Graphics g) {
        int w = getSize().width;
        int h = getSize().height;
        if (img == null) {
            super.paint(g);
            g.setColor(Color.black);
            FontMetrics fm = g.getFontMetrics();
            int x = (w - fm.stringWidth(calcString)) / 2;
            int y = h / 2;
            g.drawString(calcString, x, y);
        } else {
            g.drawImage(img, 0, 0, w, h, this);
        }
    }

    public void update(Graphics g) {
        paint(g);
    }

    public Dimension getMinimumSize() {
        return new Dimension(20, 20);
    }

    public Dimension getPreferredSize() {
        return new Dimension(200, 200);
    }

    public Image getImage() {
        return img;
    }

    public void setImage(Image img) {
        this.img = img;
        repaint();
    }
}

class DitherControls extends Panel implements ActionListener {
    private CardinalTextField start;
    private CardinalTextField end;
    private Button button;
    private Choice choice;
    private DitherTest applet;

    private static LayoutManager dcLayout = new FlowLayout(FlowLayout.CENTER,
                                                           10, 5);

    public DitherControls(DitherTest app, int s, int e, int type,
                          boolean vertical) {
        applet = app;
        setLayout(dcLayout);
        add(new Label(vertical ? "Vertical" : "Horizontal"));
        add(choice = new Choice());
        choice.addItem("Noop");
        choice.addItem("Red");
        choice.addItem("Green");
        choice.addItem("Blue");
        choice.addItem("Alpha");
        choice.addItem("Saturation");
        choice.select(type);
        add(start = new CardinalTextField(Integer.toString(s), 4));
        add(end = new CardinalTextField(Integer.toString(e), 4));
    }

    /* puts on the button */
    public void addRenderButton() {
        add(button = new Button("New Image"));
        button.addActionListener(this);
    }

    /* retrieves data from the user input fields */
    public int getParams(int vals[]) {
        try {
            vals[0] = scale(Integer.parseInt(start.getText()));
        } catch (NumberFormatException nfe) {
            vals[0] = 0;
        }
        try {
            vals[1] = scale(Integer.parseInt(end.getText()));
        } catch (NumberFormatException nfe) {
            vals[1] = 255;
        }
        return choice.getSelectedIndex();
    }

    /* fits the number between 0 and 255 inclusive */
    private int scale(int number) {
        if (number < 0) {
            number = 0;
        } else if (number > 255) {
            number = 255;
        }
        return number;
    }

    /* called when user clicks the button */
    public void actionPerformed(ActionEvent e) {
        if (e.getSource() == button) {
            applet.start();
        }
    }
}

class CardinalTextField extends TextField {

    String oldText = null;

    public CardinalTextField(String text, int columns) {
        super(text, columns);
        enableEvents(AWTEvent.KEY_EVENT_MASK | AWTEvent.TEXT_EVENT_MASK);
        oldText = getText();
    }

    // Consume non-digit KeyTyped events
    // Note that processTextEvent kind of eliminates the need for this
    // function, but this is neater, since ideally, it would prevent
    // the text from appearing at all.  Sigh.  See bugid 4100317/4114565.
    //
    protected void processEvent(AWTEvent evt) {
        int id = evt.getID();
        if (id != KeyEvent.KEY_TYPED) {
            super.processEvent(evt);
            return;
        }

        KeyEvent kevt = (KeyEvent) evt;
        char c = kevt.getKeyChar();

        // Digits, backspace, and delete are okay
        // Note that the minus sign is not allowed (neither is decimal)
        if (Character.isDigit(c) || (c == '\b') || (c == '\u007f')) {
            super.processEvent(evt);
            return;
        }

        Toolkit.getDefaultToolkit().beep();
        kevt.consume();
    }

    // Should consume TextEvents for non-integer Strings
    // Store away the text in the tf for every TextEvent
    // so we can revert to it on a TextEvent (paste, or
    // legal key in the wrong location) with bad text
    //
    // Note: it would be easy to extend this to an eight-bit
    // TextField (range 0-255), but I'll leave it as-is.
    //
    protected void processTextEvent(TextEvent te) {
        // The empty string is okay, too
        String newText = getText();
        if (newText.equals("") || textIsCardinal(newText)) {
            oldText = newText;
            super.processTextEvent(te);
            return;
        }

        Toolkit.getDefaultToolkit().beep();
        setText(oldText);
    }

    // Returns true for Cardinal (non-negative) numbers
    // Note that the empty string is not allowed
    private boolean textIsCardinal(String textToCheck) {
        int value = -1;

        try {
            value = Integer.parseInt(textToCheck, 10);
            return (value >= 0);
        } catch (NumberFormatException nfe) {
            return false;
        }
    }
}
