package org.sunflow.core.display;

import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.image.BufferedImage;

import javax.swing.JFrame;
import javax.swing.JPanel;

import org.sunflow.SunflowAPI;
import org.sunflow.core.Display;
import org.sunflow.image.Color;
import org.sunflow.system.Timer;

@SuppressWarnings("serial")
public class FastDisplay extends JPanel implements Display {
    private JFrame frame;
    private BufferedImage image;
    private int[] pixels;
    private Timer t;
    private float seconds;
    private int frames;

    public FastDisplay() {
        image = null;
        frame = null;
        t = new Timer();
        frames = 0;
        seconds = 0;
    }

    public synchronized void imageBegin(int w, int h, int bucketSize) {
        if (frame != null && image != null && w == image.getWidth() && h == image.getHeight()) {
            // nothing to do
        } else {
            // allocate new framebuffer
            pixels = new int[w * h];
            image = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB);
            // prepare frame
            if (frame == null) {
                setPreferredSize(new Dimension(w, h));
                frame = new JFrame("Sunflow v" + SunflowAPI.VERSION);
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.addKeyListener(new KeyAdapter() {
                    @Override
                    public void keyPressed(KeyEvent e) {
                        if (e.getKeyCode() == KeyEvent.VK_ESCAPE)
                            System.exit(0);
                    }
                });
                frame.setContentPane(this);
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        }
        // start counter
        t.start();
    }

    public void imagePrepare(int x, int y, int w, int h, int id) {
    }

    public void imageUpdate(int x, int y, int w, int h, Color[] data, float[] alpha) {
        int iw = image.getWidth();
        int off = x + iw * y;
        iw -= w;
        for (int j = 0, index = 0; j < h; j++, off += iw)
            for (int i = 0; i < w; i++, index++, off++)
                pixels[off] = 0xFF000000 | data[index].toRGB();
    }

    public void imageFill(int x, int y, int w, int h, Color c, float alpha) {
        int iw = image.getWidth();
        int off = x + iw * y;
        iw -= w;
        int rgb = 0xFF000000 | c.toRGB();
        for (int j = 0, index = 0; j < h; j++, off += iw)
            for (int i = 0; i < w; i++, index++, off++)
                pixels[off] = rgb;
    }

    public synchronized void imageEnd() {
        // copy buffer
        image.setRGB(0, 0, image.getWidth(), image.getHeight(), pixels, 0, image.getWidth());
        repaint();
        // update stats
        t.end();
        seconds += t.seconds();
        frames++;
        if (seconds > 1) {
            // display average fps every second
            frame.setTitle(String.format("Sunflow v%s - %.2f fps", SunflowAPI.VERSION, frames / seconds));
            frames = 0;
            seconds = 0;
        }
    }

    @Override
    public synchronized void paint(Graphics g) {
        if (image == null)
            return;
        g.drawImage(image, 0, 0, null);
    }
}