/*

*/

import renderer.scene.*;
import renderer.scene.util.Assets;
import renderer.models_L.*;
import renderer.pipeline.*;
import renderer.framebuffer.*;

import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JButton;
import java.awt.BorderLayout;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
import java.io.File;

/**
   This class is the Model, the View, and part of the Controller.
*/
public class ButtonsAndModels_v1 implements ActionListener
{
   private static final String assets = Assets.getPath();

   // The gui state data (the Model in MVC).
   public final Scene scene;
   public final FrameBufferPanel fbp;
   public int currentModel = 0;

   private ButtonsAndModels_v1()
   {
      scene = new Scene("ButtonsAndModels_v1");

      scene.addPosition(new Position(new Cube4(12, 14, 15),
                                     new Vector(0, 0, -3)));
      scene.addPosition(new Position(new ObjSimpleModel(
                                        new File(assets + "cow.obj")),
                                     new Vector(0, 0, -2)));
      scene.addPosition(new Position(new ParametricSurface(),
                                     new Vector(0, 0, -2)));
      scene.addPosition(new Position(new Torus(0.75, 0.25, 12, 16),
                                     new Vector(0, 0, -2)));

      // Make the models invisible, except for the current model.
      for (final Position p : scene.positionList)
      {
         p.visible = false;
      }
      currentModel = 0;
      scene.getPosition(currentModel).visible = true;

      Rasterize.doClipping = true;


      // Create a FrameBufferPanel that holds a FrameBuffer.
      final int width  = 700;
      final int height = 700;
      fbp = new FrameBufferPanel(width, height);

      // Create a JFrame that will hold the FrameBufferPanel.
      final JFrame jf = new JFrame("Buttons And Models v1");
      jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      jf.getContentPane().add(fbp, BorderLayout.CENTER);

      final JPanel p = new JPanel();
      final JButton b1 = new JButton("Model 1");
      p.add(b1);
      final JButton b2 = new JButton("Model 2");
      p.add(b2);
      final JButton b3 = new JButton("Model 3");
      p.add(b3);
      final JButton b4 = new JButton("Model 4");
      p.add(b4);
      jf.add(p, BorderLayout.NORTH);
      // Register this object as the event listener for button events.
      b1.addActionListener(this);
      b2.addActionListener(this);
      b3.addActionListener(this);
      b4.addActionListener(this);  // this's role as Controller

      // Add two more buttons to move the models.
      final JButton b5 = new JButton("Backwards");
      p.add(b5);
      final JButton b6 = new JButton("Forwards");
      p.add(b6);

      MoveHandler mh = new MoveHandler(this); // this's role as Model and View

      b5.addActionListener(mh);
      b6.addActionListener(mh);

      // Make the gui visible.
      jf.pack();
      jf.setLocationRelativeTo(null);
      jf.setVisible(true);

      // Render.
      final FrameBuffer fb = fbp.getFrameBuffer();
      Pipeline.render(scene, fb);
      fbp.repaint();
   }//ButtonsAndModels_v1 constructor


   // This is part of the Controller part of MVC.
   public void actionPerformed(ActionEvent e)
   {
      //System.out.println(e);

      scene.getPosition(currentModel).visible = false;

      final String cmd = e.getActionCommand();

      if (cmd.equals("Model 1"))
      {
         currentModel = 0;
      }
      else if (cmd.equals("Model 2"))
      {
         currentModel = 1;
      }
      else if (cmd.equals("Model 3"))
      {
         currentModel = 2;
      }
      else
      {
         currentModel = 3;
      }

      scene.getPosition(currentModel).visible = true;

      // Render again (update the View).
      final FrameBuffer fb = fbp.getFrameBuffer();
      fb.clearFB();
      Pipeline.render(scene, fb);
      fbp.repaint();
   }


   /**
      Create an instance of this class which has
      the affect of creating the GUI application.
   */
   public static void main(String[] args)
   {
      // We need to call the program's constructor in the
      // Java GUI Event Dispatch Thread, otherwise we get a
      // race condition between the constructor (running in
      // the main() thread) and the very first ComponentEvent
      // (running in the EDT).
      javax.swing.SwingUtilities.invokeLater(
         () -> new ButtonsAndModels_v1()
      );
   }
}//ButtonsAndModels_v1 class


// This private class is another part of the Controller.
class MoveHandler implements ActionListener
{
   final ButtonsAndModels_v1 bm;

   public MoveHandler(final ButtonsAndModels_v1 bm)
   {
      this.bm = bm;
   }

   public void actionPerformed(ActionEvent e)
   {
      //System.out.println(e);

      final Vector v = bm.scene.getPosition(bm.currentModel).getTranslation();
      final double x = v.x;
      final double y = v.y;
      final double z = v.z;

      final String cmd = e.getActionCommand();

      final double newZ;
      if (cmd.equals("Backwards"))
      {
        newZ = z - 0.5;
      }
      else  // "Forwards"
      {
        newZ = z + 0.5;
      }

      bm.scene.getPosition(bm.currentModel).translate(x, y, newZ);

      // Render again (update the View).
      final FrameBuffer fb = bm.fbp.getFrameBuffer();
      fb.clearFB();
      Pipeline.render(bm.scene, fb);
      bm.fbp.repaint();
   }
}//MoveHandler class
