package renderer.canvas;

import renderer.Resolution;
import renderer.Scheduler;
import renderer.debug.DebugOverlay;

import javax.swing.*;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.awt.image.DataBufferInt;
import java.awt.image.RenderedImage;

public class RenderTarget extends JPanel {

    private BufferedImage target;
    private int[] pixels;
    private ContributionBuffer buffer;
    private DebugOverlay overlay;

    private boolean visualizeThreads = false;

    public RenderTarget(Resolution resolution) {
        super();
        this.overlay = new DebugOverlay();
        this.overlay.setup();
        this.buildBuffer(resolution);

        setLayout(new BorderLayout());
        add(this.overlay.getRoot(), BorderLayout.NORTH);
    }

    public void buildBuffer(Resolution resolution) {
        int scaledWidth = resolution.getScaledWidth();
        int scaledHeight = resolution.getScaledHeight();

        this.target = new BufferedImage(scaledWidth, scaledHeight, BufferedImage.TYPE_INT_ARGB);
        this.pixels = ((DataBufferInt) target.getRaster().getDataBuffer() ).getData();
        this.buffer = new ContributionBuffer(scaledWidth, scaledHeight);
    }

    public void refresh() {
        this.buffer.blit(this.pixels);
    }

    public ContributionBuffer getBuffer() {
        return buffer;
    }

    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);

        g.drawImage(this.target, 0, 0, this.getWidth(), this.getHeight(), null);

        if (visualizeThreads) {
            int tileWidth = getWidth() / Scheduler.THREADS_PER_SIDE;
            int tileHeight = getHeight() / Scheduler.THREADS_PER_SIDE;

            Graphics2D g2 = (Graphics2D) g.create();
            g2.setColor(Color.MAGENTA);
            g2.setStroke(new BasicStroke(2));

            for (int x = 1; x < Scheduler.THREADS_PER_SIDE; x++) {
                g2.drawLine(0, x * tileHeight, getWidth(), x * tileHeight);
                g2.drawLine(x * tileWidth, 0, x * tileWidth, getHeight());
            }
        }
    }

    public DebugOverlay getOverlay() {
        return overlay;
    }

    public RenderedImage getImage() {
        return this.target;
    }
}
