package com.marginallyclever;

import com.jogamp.opengl.*;
import com.jogamp.opengl.awt.GLJPanel;

import javax.swing.*;
import java.awt.*;

/**
 * Uses Modern Docking to create three kinds of DockingPanels: a tree, an output, and many text editor panels.
 * each type of panel automatically group together when created.
 */
public class Editor3 extends JFrame {
    //private final FPSAnimator animator = new FPSAnimator(30);
    private GLJPanel glCanvas;

    public static void main(String[] args) {
        SwingUtilities.invokeLater(()->(new Editor3()).setVisible(true));
    }

    public Editor3() {
        super("Demo");

        // show the main window
        setSize(800, 600);
        setLocationRelativeTo(null);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        var bar = new JMenuBar();
        var menu = new JMenu("File");
        menu.add("New");
        bar.add(menu);
        add(bar, BorderLayout.NORTH);

        // add opengl panel
        add(createGLPanel(), BorderLayout.CENTER);
        var ta = new JTextArea();
        ta.setText("This is a demo text");
        add(new JScrollPane(ta), BorderLayout.SOUTH);
    }

    private GLJPanel createGLPanel() {
        try {
            GLCapabilities capabilities = getCapabilities();
            glCanvas = new GLJPanel(capabilities);
        } catch(GLException e) {
            e.printStackTrace();
            return null;
        }
        // add a rotating triangle
        glCanvas.addGLEventListener(new GLEventListener() {
            int width,height;
            @Override
            public void init(GLAutoDrawable glAutoDrawable) {
                GL2 gl2 = glAutoDrawable.getGL().getGL2();
                // vsync on
                gl2.setSwapInterval(1);
                // enable anti-aliasing
                gl2.glEnable(GL3.GL_LINE_SMOOTH);
                gl2.glEnable(GL3.GL_POLYGON_SMOOTH);
                gl2.glHint(GL3.GL_POLYGON_SMOOTH_HINT, GL3.GL_NICEST);
                gl2.glEnable(GL3.GL_MULTISAMPLE);
                // depth testing
                gl2.glEnable(GL3.GL_DEPTH_TEST);
                gl2.glDepthFunc(GL3.GL_LESS);
                gl2.glDepthMask(true);
                // Don't draw triangles facing away from camera
                gl2.glEnable(GL3.GL_CULL_FACE);
                gl2.glCullFace(GL3.GL_BACK);
                // default blending option for transparent materials
                gl2.glEnable(GL3.GL_BLEND);
                gl2.glBlendFunc(GL3.GL_SRC_ALPHA, GL3.GL_ONE_MINUS_SRC_ALPHA);
                // clear color
                gl2.glClearColor(0.5f,0.5f,0.5f,0);
            }

            @Override
            public void dispose(GLAutoDrawable glAutoDrawable) {

            }

            @Override
            public void display(GLAutoDrawable glAutoDrawable) {
                GL2 gl2 = glAutoDrawable.getGL().getGL2();
                gl2.glClear(GL2.GL_COLOR_BUFFER_BIT | GL2.GL_DEPTH_BUFFER_BIT);

                // draw a triangle
                gl2.glBegin(GL2.GL_TRIANGLES);
                gl2.glColor3f(1.0f, 0.0f, 0.0f);  gl2.glVertex2f(-0.5f, -0.5f);
                gl2.glColor3f(0.0f, 1.0f, 0.0f);  gl2.glVertex2f(0.5f, -0.5f);
                gl2.glColor3f(0.0f, 0.0f, 1.0f);  gl2.glVertex2f(0.0f, 0.5f);
                gl2.glEnd();
            }

            @Override
            public void reshape(GLAutoDrawable glAutoDrawable, int x, int y, int width, int height) {
                this.width = width;
                this.height = height;
            }
        });

        return glCanvas;
    }

    private GLCapabilities getCapabilities() {
        GLProfile profile = GLProfile.getMaxProgrammable(true);
        GLCapabilities capabilities = new GLCapabilities(profile);
        capabilities.setHardwareAccelerated(true);
        capabilities.setBackgroundOpaque(true);
        capabilities.setDoubleBuffered(true);
        capabilities.setStencilBits(8);
        capabilities.setDepthBits(32);  // 32 bit depth buffer is floating point

        StringBuilder sb = new StringBuilder();
        capabilities.toString(sb);
        return capabilities;
    }
}