package cz.fidentis.analyst.gui;

import com.jogamp.opengl.GLCapabilities;
import com.jogamp.opengl.GLEventListener;
import com.jogamp.opengl.GLProfile;
import com.jogamp.opengl.awt.GLCanvas;
import cz.fidentis.analyst.face.HumanFace;
import cz.fidentis.analyst.mesh.io.ModelFileFilter;
import cz.fidentis.analyst.mesh.core.MeshModel;
import com.jogamp.opengl.util.FPSAnimator;

import java.awt.Color;
import java.awt.Cursor;
import java.awt.Dimension;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Scanner;
import java.util.Timer;
import java.util.TimerTask;
import javax.swing.ImageIcon;
import javax.swing.JFileChooser;
import javax.swing.JOptionPane;

/**
 * Canvas for displaying models containing GLCanvas and navigation.
 * 
 * @author Natalia Bebjakova 
 */
public class Canvas extends javax.swing.JPanel {
    
    protected GLCanvas glCanvas;
    protected long startClickTime = 0;
    
    protected TimerTask task;
    protected Timer timer;
    
    protected GeneralGLEventListener listener;
     
    /**
     * Mouse adapter for 3D manipulation
     */
    protected Manipulator3D manipulator;

    /**
     * animator's target frames per second
     */
    private static final int FPS = 60; 
    private final FPSAnimator animator;
    
    /**
     * decides if model is displayed as wire-frame 
     */
    protected static boolean drawWireModel;

    /**
     * decides if the symmetryPlane is displayed
     */
    protected static boolean drawSymmetryPlane;
    
    /**
     * original face that is loaded from file
     */
    protected HumanFace loadedFace;
    
    protected boolean loaded;   
    
    /**
     * 
     * @return true if model is loaded on canvas, false otherwise
     */
    public boolean isLoaded() {
        return loaded;
    }
    
    /**
     * Creates new form Canva
     */
    public Canvas() {
        initComponents();
        
        // gl version 2 is used
        GLCapabilities capabilities = new GLCapabilities(GLProfile.get(GLProfile.GL2));
        capabilities.setDoubleBuffered(true);
       
        // creates new glCanvas panel for displaying model
        glCanvas = new GLCanvas(capabilities);
        jPanel1.add(glCanvas);
        glCanvas.setVisible(false);     
        glCanvas.setBackground(Color.black);
        
        // enables glCanvas to react to events
        glCanvas.requestFocusInWindow();        
        glCanvas.setSize(getWidth() - getInsets().left - getInsets().right, getHeight() - getInsets().top - getInsets().bottom);
       
        // enables animated transition 
        animator = new FPSAnimator(glCanvas, FPS, true);
        animator.start();
        listener = new GeneralGLEventListener(this);
        
        // enables 3D manipualtion
        manipulator = new Manipulator3D(listener);
        setMouseListeners();

        this.validate();   
    }
    
    private void removeMoseListeners() {
        glCanvas.removeMouseListener(this.manipulator);
        glCanvas.removeMouseMotionListener(this.manipulator);
        glCanvas.removeMouseWheelListener(this.manipulator);
    }
    
    private void setMouseListeners() {
        glCanvas.addMouseListener(manipulator);
        glCanvas.addMouseMotionListener(manipulator);
        glCanvas.addMouseWheelListener(manipulator);
    }
    
    /**
     * Sets new mouse listeners for this canvas
     * 
     * @param manipulator new Manipulator3D, probably with different listener
     */
    public void setManipulator(Manipulator3D manipulator) {
        removeMoseListeners();
        this.manipulator = manipulator;
        setMouseListeners();
    }
    
    /**
     * Changing the size of glCanvas
     * 
     * @param d New size of glCanvas
     */
    public void resizeCanvas(Dimension d) {
        jPanel1.setSize(d);
        glCanvas.setSize(d);
        this.validate();
        this.repaint();
        loadModelButton.setLocation(this.getWidth() / 2 - 35, this.getHeight() / 2 - 40);
    }
    
    /**
     * 
     * @return Original face that is loaded from file
     */
    public HumanFace getLoadedFace() {
        return loadedFace;
    }
    
    /**
     * Sets GLListener of the canvas 
     * 
     * @param listener GLListener for manipulation with model 
     */
    public void setListener(GeneralGLEventListener listener) {
        this.listener = listener;
    }
    
    /**
     * 
     * @param drawWire Decides if model is displayed as wife-frame
     */
    public static void setDrawWired(boolean drawWire) {
        drawWireModel = drawWire;
    }

    /**
     * 
     * @return Returns if model is displayed as wife-frame
     */
    public boolean getDrawWired(){
        return drawWireModel;
    }

    /**
     *
     * @param drawSymmetry Decides if the symmetry plane is displayed
     */
    public static void setDrawSymmetryPlane(boolean drawSymmetry) {
        drawSymmetryPlane = drawSymmetry;
    }

    /**
     *
     * @return Returns if the symmetry plane is displayed
     */
    public boolean getDrawSymmetryPlane(){
        return drawSymmetryPlane;
    }

    /**
     *
     * @param v Decides if button for loading model is visible
     */
    public void setImportLabelVisible(Boolean v) {
        loadModelButton.setVisible(v);
    }
    
    /**
     * Loads model selected in file chooser by user
     */
    public void loadModel () {
        String[] extensions = new String[2];
        extensions[0] = "obj";
        extensions[1] = "OBJ";
        
        //enables to shows just .obj files in file chooser
        ModelFileFilter filter = new ModelFileFilter(extensions, "*.obj");
        JFileChooser jFileChooser1 = new JFileChooser(getPrefferedModelPath());
        jFileChooser1.setPreferredSize(new Dimension (800,500));
       
        jFileChooser1.addChoosableFileFilter(filter);        
       
        //file chooser will appear on top of glCanvas
        jFileChooser1.showOpenDialog(this);
        jFileChooser1.setDialogTitle("Import obj file");
        
        setPrefferedModelPath(jFileChooser1.getCurrentDirectory().toString());
        
        File[] fileArray = new File[1];
        //saves selected file by user as first element in array
        fileArray[0] = jFileChooser1.getSelectedFile();

        //testing getting path TODO
        //JOptionPane.showConfirmDialog(null,
        //        fileArray[0].getAbsoluteFile(), "", JOptionPane.YES_NO_OPTION, JOptionPane.WARNING_MESSAGE);

        if (fileArray.length <= 0) {
            System.out.print("No file chosen.");
        } else {
            this.addModel(fileArray[0]);
        }       
        glCanvas.setVisible(true);
    }
    
    private void setPrefferedModelPath(String s) {
        //TODO remove duplicate with PreferenceTopComponent
        try {
            FileWriter rewriter = new FileWriter("preferences.fip", false);
            rewriter.write(s);
            rewriter.close();
        } catch (IOException ex) {
            ex.printStackTrace();
        }   
    }
    
    private String getPrefferedModelPath() {
        //TODO remove duplicate with PreferenceTopComponent
        String data = "";
        try {
            File myObj = new File(/*propPath + */"preferences.fip");
            if (myObj.length() == 0)
                return data;
            try (Scanner myReader = new Scanner(myObj)) {
                data = myReader.nextLine();
            }            
        } catch (FileNotFoundException e) {
            System.out.println("An error occurred.");
            e.printStackTrace();
        }
        return data;
    }

    /**
     * Loads the model in .obj format from file and adds this model to listener for displaying.
     * If file does not contain 3D model or model is not correct, shows dialog with message
     *
     * @param file File from which model will be read
     */
    private void addModel (final File file) {
        try {
            loadedFace = new HumanFace(new File (file.getPath()));

            if (loadedFace.getMeshModel() != null) {
                // listener enables to manipulate and interact with model
                listener.setCameraPosition(0, 0, 300);
                glCanvas.addGLEventListener((GLEventListener) listener);
                listener.setModel(loadedFace.getMeshModel());
                listener.rotationAndSizeRestart();
                loadModelButton.setVisible(false);
                loaded = true;
            }           
        } catch (Exception e) {
            System.out.println(e.getMessage());
            JOptionPane.showMessageDialog(this, "File doesn't contain any model", "Model is not loaded.",
                    0, new ImageIcon(getClass().getResource("/notLoadedModel.png")));
            System.out.println ("File doesn't contain any model");
            loaded = false;               
        }
    }
    
    /**
     * reset position of the displayed model
     */
    public void resetPosition(){
        listener.rotationAndSizeRestart();
    }
    
    /**
     * Changes the model to be displayed
     * 
     * @param model New model that will be displayed on canvas
     */
    public void changeModel(MeshModel model) {
        MeshModel newModel = new MeshModel(model);
        listener.setModel(newModel);
    }
    
    /**
     * Returns the model which is displayed on canvas
     * 
     * @return Model that is displayed on canvas
     */
    public MeshModel getModel() {
        return listener.getModel();
    }
   
    
    /**
     * This method is called from within the constructor to initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is always
     * regenerated by the Form Editor.
     * 
     * Generated code from NetBeans
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        jLayeredPane1 = new javax.swing.JLayeredPane();
        resetButton = new javax.swing.JLabel();
        upNavigationButton = new javax.swing.JButton();
        leftNavigationButton = new javax.swing.JButton();
        minusNavigationButton = new javax.swing.JButton();
        downNavigationButton = new javax.swing.JButton();
        plusNavigationButton = new javax.swing.JButton();
        jLabel1 = new javax.swing.JLabel();
        loadModelButton = new javax.swing.JLabel();
        rightNavigationButton1 = new javax.swing.JButton();
        whiteBackroundButton = new javax.swing.JLabel();
        blackBackroundButton = new javax.swing.JLabel();
        jPanel1 = new javax.swing.JPanel();

        setBackground(new java.awt.Color(0, 0, 0));
        setLayout(new java.awt.BorderLayout());

        jLayeredPane1.setBackground(new java.awt.Color(40, 40, 40));
        jLayeredPane1.setToolTipText("");
        jLayeredPane1.setOpaque(true);
        jLayeredPane1.addComponentListener(new java.awt.event.ComponentAdapter() {
            public void componentResized(java.awt.event.ComponentEvent evt) {
                jLayeredPane1ComponentResized(evt);
            }
            public void componentShown(java.awt.event.ComponentEvent evt) {
                jLayeredPane1ComponentShown(evt);
            }
        });

        resetButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/resetButton.png"))); // NOI18N
        resetButton.setToolTipText("Reset position of model");
        resetButton.setCursor(new java.awt.Cursor(java.awt.Cursor.HAND_CURSOR));
        resetButton.addMouseMotionListener(new java.awt.event.MouseMotionAdapter() {
            public void mouseMoved(java.awt.event.MouseEvent evt) {
                resetButtonMouseMoved(evt);
            }
        });
        resetButton.addMouseListener(new java.awt.event.MouseAdapter() {
            public void mouseClicked(java.awt.event.MouseEvent evt) {
                resetButtonMouseClicked(evt);
            }
            public void mouseExited(java.awt.event.MouseEvent evt) {
                resetButtonMouseExited(evt);
            }
        });
        jLayeredPane1.add(resetButton);
        resetButton.setBounds(60, 40, 30, 30);

        upNavigationButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/upButton.png"))); // NOI18N
        upNavigationButton.setToolTipText("Rotate up");
        upNavigationButton.setBorderPainted(false);
        upNavigationButton.setContentAreaFilled(false);
        upNavigationButton.setCursor(new java.awt.Cursor(java.awt.Cursor.HAND_CURSOR));
        upNavigationButton.addMouseListener(new java.awt.event.MouseAdapter() {
            public void mousePressed(java.awt.event.MouseEvent evt) {
                upNavigationButtonMousePressed(evt);
            }
            public void mouseReleased(java.awt.event.MouseEvent evt) {
                upNavigationButtonMouseReleased(evt);
            }
        });
        jLayeredPane1.setLayer(upNavigationButton, javax.swing.JLayeredPane.MODAL_LAYER);
        jLayeredPane1.add(upNavigationButton);
        upNavigationButton.setBounds(60, 10, 30, 30);

        leftNavigationButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/leftButton.png"))); // NOI18N
        leftNavigationButton.setToolTipText("Rotate left");
        leftNavigationButton.setBorderPainted(false);
        leftNavigationButton.setContentAreaFilled(false);
        leftNavigationButton.setCursor(new java.awt.Cursor(java.awt.Cursor.HAND_CURSOR));
        leftNavigationButton.addMouseListener(new java.awt.event.MouseAdapter() {
            public void mousePressed(java.awt.event.MouseEvent evt) {
                leftNavigationButtonMousePressed(evt);
            }
            public void mouseReleased(java.awt.event.MouseEvent evt) {
                leftNavigationButtonMouseReleased(evt);
            }
        });
        jLayeredPane1.setLayer(leftNavigationButton, javax.swing.JLayeredPane.MODAL_LAYER);
        jLayeredPane1.add(leftNavigationButton);
        leftNavigationButton.setBounds(30, 40, 30, 30);

        minusNavigationButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/minus.png"))); // NOI18N
        minusNavigationButton.setToolTipText("Zoom out");
        minusNavigationButton.setBorderPainted(false);
        minusNavigationButton.setContentAreaFilled(false);
        minusNavigationButton.setCursor(new java.awt.Cursor(java.awt.Cursor.HAND_CURSOR));
        minusNavigationButton.addMouseListener(new java.awt.event.MouseAdapter() {
            public void mousePressed(java.awt.event.MouseEvent evt) {
                minusNavigationButtonMousePressed(evt);
            }
            public void mouseReleased(java.awt.event.MouseEvent evt) {
                minusNavigationButtonMouseReleased(evt);
            }
        });
        jLayeredPane1.setLayer(minusNavigationButton, javax.swing.JLayeredPane.MODAL_LAYER);
        jLayeredPane1.add(minusNavigationButton);
        minusNavigationButton.setBounds(90, 90, 30, 30);

        downNavigationButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/downButton.png"))); // NOI18N
        downNavigationButton.setToolTipText("Rotate down");
        downNavigationButton.setBorderPainted(false);
        downNavigationButton.setContentAreaFilled(false);
        downNavigationButton.setCursor(new java.awt.Cursor(java.awt.Cursor.HAND_CURSOR));
        downNavigationButton.addMouseListener(new java.awt.event.MouseAdapter() {
            public void mousePressed(java.awt.event.MouseEvent evt) {
                downNavigationButtonMousePressed(evt);
            }
            public void mouseReleased(java.awt.event.MouseEvent evt) {
                downNavigationButtonMouseReleased(evt);
            }
        });
        jLayeredPane1.setLayer(downNavigationButton, javax.swing.JLayeredPane.MODAL_LAYER);
        jLayeredPane1.add(downNavigationButton);
        downNavigationButton.setBounds(60, 70, 30, 30);

        plusNavigationButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/plus.png"))); // NOI18N
        plusNavigationButton.setToolTipText("Zoom in");
        plusNavigationButton.setBorderPainted(false);
        plusNavigationButton.setContentAreaFilled(false);
        plusNavigationButton.setCursor(new java.awt.Cursor(java.awt.Cursor.HAND_CURSOR));
        plusNavigationButton.addMouseListener(new java.awt.event.MouseAdapter() {
            public void mousePressed(java.awt.event.MouseEvent evt) {
                plusNavigationButtonMousePressed(evt);
            }
            public void mouseReleased(java.awt.event.MouseEvent evt) {
                plusNavigationButtonMouseReleased(evt);
            }
        });
        jLayeredPane1.setLayer(plusNavigationButton, javax.swing.JLayeredPane.MODAL_LAYER);
        jLayeredPane1.add(plusNavigationButton);
        plusNavigationButton.setBounds(30, 90, 30, 30);

        jLabel1.setIcon(new javax.swing.ImageIcon(getClass().getResource("/navigBackground.png"))); // NOI18N
        jLayeredPane1.add(jLabel1);
        jLabel1.setBounds(30, 10, 90, 90);

        loadModelButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/loadCanva.png"))); // NOI18N
        loadModelButton.setToolTipText("");
        loadModelButton.setCursor(new java.awt.Cursor(java.awt.Cursor.HAND_CURSOR));
        loadModelButton.addMouseMotionListener(new java.awt.event.MouseMotionAdapter() {
            public void mouseMoved(java.awt.event.MouseEvent evt) {
                loadModelButtonMouseMoved(evt);
            }
        });
        loadModelButton.addMouseListener(new java.awt.event.MouseAdapter() {
            public void mouseClicked(java.awt.event.MouseEvent evt) {
                loadModelButtonMouseClicked(evt);
            }
            public void mouseExited(java.awt.event.MouseEvent evt) {
                loadModelButtonMouseExited(evt);
            }
        });
        jLayeredPane1.add(loadModelButton);
        loadModelButton.setBounds(200, 100, 210, 220);

        rightNavigationButton1.setIcon(new javax.swing.ImageIcon(getClass().getResource("/rightButton.png"))); // NOI18N
        rightNavigationButton1.setToolTipText("Rotate right");
        rightNavigationButton1.setBorderPainted(false);
        rightNavigationButton1.setContentAreaFilled(false);
        rightNavigationButton1.setCursor(new java.awt.Cursor(java.awt.Cursor.HAND_CURSOR));
        rightNavigationButton1.addMouseListener(new java.awt.event.MouseAdapter() {
            public void mousePressed(java.awt.event.MouseEvent evt) {
                rightNavigationButton1MousePressed(evt);
            }
            public void mouseReleased(java.awt.event.MouseEvent evt) {
                rightNavigationButton1MouseReleased(evt);
            }
        });
        jLayeredPane1.setLayer(rightNavigationButton1, javax.swing.JLayeredPane.MODAL_LAYER);
        jLayeredPane1.add(rightNavigationButton1);
        rightNavigationButton1.setBounds(90, 40, 30, 30);

        whiteBackroundButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/whiteBackroundCanvas.png"))); // NOI18N
        whiteBackroundButton.setToolTipText("White backround");
        whiteBackroundButton.setCursor(new java.awt.Cursor(java.awt.Cursor.HAND_CURSOR));
        whiteBackroundButton.addMouseListener(new java.awt.event.MouseAdapter() {
            public void mouseClicked(java.awt.event.MouseEvent evt) {
                whiteBackroundButtonMouseClicked(evt);
            }
        });
        jLayeredPane1.add(whiteBackroundButton);
        whiteBackroundButton.setBounds(50, 130, 56, 56);

        blackBackroundButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/blackBackroundCanvas.png"))); // NOI18N
        blackBackroundButton.setToolTipText("Dark background");
        blackBackroundButton.setCursor(new java.awt.Cursor(java.awt.Cursor.HAND_CURSOR));
        blackBackroundButton.addMouseListener(new java.awt.event.MouseAdapter() {
            public void mouseClicked(java.awt.event.MouseEvent evt) {
                blackBackroundButtonMouseClicked(evt);
            }
        });
        jLayeredPane1.add(blackBackroundButton);
        blackBackroundButton.setBounds(50, 190, 56, 56);

        jPanel1.setBackground(new java.awt.Color(0, 0, 0));
        jPanel1.setLayout(new java.awt.BorderLayout());
        jLayeredPane1.add(jPanel1);
        jPanel1.setBounds(0, 0, 0, 0);

        add(jLayeredPane1, java.awt.BorderLayout.CENTER);
    }// </editor-fold>//GEN-END:initComponents

    /**
     * 
     * @param evt Resizing glCanvas cantaining components
     */
    private void jLayeredPane1ComponentResized(java.awt.event.ComponentEvent evt) {//GEN-FIRST:event_jLayeredPane1ComponentResized
        jPanel1.setBounds(0, 0, jLayeredPane1.getWidth(), jLayeredPane1.getHeight());
        glCanvas.setBounds(jLayeredPane1.getX(), jLayeredPane1.getY(), jLayeredPane1.getWidth(), jLayeredPane1.getHeight());
        loadModelButton.setLocation(this.getWidth() / 2 - 35, this.getHeight() / 2 - 40);
    }//GEN-LAST:event_jLayeredPane1ComponentResized

    /**
     * 
     * @param evt Showing glCanvas cantaining components
     */
    private void jLayeredPane1ComponentShown(java.awt.event.ComponentEvent evt) {//GEN-FIRST:event_jLayeredPane1ComponentShown
        jPanel1.setBounds(0, 0, jLayeredPane1.getWidth(), jLayeredPane1.getHeight());
        glCanvas.setBounds(jLayeredPane1.getX(), jLayeredPane1.getY(), jLayeredPane1.getWidth(), jLayeredPane1.getHeight());
        loadModelButton.setLocation(this.getWidth() / 2 - 35, this.getHeight() / 2 - 40);
    }//GEN-LAST:event_jLayeredPane1ComponentShown

    /**
     * 
     * @param evt Enables to rotate left the model when left navigation button is pressed
     */
    private void leftNavigationButtonMousePressed(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_leftNavigationButtonMousePressed
        timer = new Timer();
        startClickTime = System.currentTimeMillis();
        task = new TimerTask() {
            @Override
            public void run() {
                listener.rotateLeft(2);
            }
        };
        timer.schedule(task, 500, 100);
        leftNavigationButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/leftButtonPressed.png")));
    }//GEN-LAST:event_leftNavigationButtonMousePressed

    /**
     * 
     * @param evt Enables to rotate up the model when up navigation button is pressed
     */
    private void upNavigationButtonMousePressed(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_upNavigationButtonMousePressed
        timer = new Timer();
        startClickTime = System.currentTimeMillis();
        task = new TimerTask() {
            @Override
            public void run() {
                listener.rotateUp(2);
            }
        };
        timer.schedule(task, 500, 100);
        upNavigationButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/upButtonPressed.png")));
    }//GEN-LAST:event_upNavigationButtonMousePressed

    /**
     * 
     * @param evt Enables to rotate down the model when down navigation button is pressed
     */
    private void downNavigationButtonMousePressed(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_downNavigationButtonMousePressed
        timer = new Timer();
        startClickTime = System.currentTimeMillis();
        task = new TimerTask() {
            @Override
            public void run() {
                listener.rotateDown(2);
            }
        };
        timer.schedule(task, 500, 100);
        downNavigationButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/downButtonPressed.png")));
    }//GEN-LAST:event_downNavigationButtonMousePressed

    /**
     * 
     * @param evt Enables to zoom in the model when plus navigation button is pressed
     */
    private void plusNavigationButtonMousePressed(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_plusNavigationButtonMousePressed
        timer = new Timer();
        startClickTime = System.currentTimeMillis();
        task = new TimerTask() {
            @Override
            public void run() {
                listener.zoomIn(3);
            }
        };
        timer.schedule(task, 500, 100);
        plusNavigationButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/plusPressed.png")));
    }//GEN-LAST:event_plusNavigationButtonMousePressed
 
  /**
  * 
  * @param evt Enables to zoom out the model when minus navigation button is pressed
  */
    private void minusNavigationButtonMousePressed(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_minusNavigationButtonMousePressed
        timer = new Timer();
        startClickTime = System.currentTimeMillis();
        task = new TimerTask() {
            @Override
            public void run() {
                listener.zoomOut(3);
            }
        };
        timer.schedule(task, 500, 100);
        minusNavigationButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/minusPressed.png")));
    }//GEN-LAST:event_minusNavigationButtonMousePressed

    /**
     * 
     * @param evt Stops rotating left
     */
    private void leftNavigationButtonMouseReleased(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_leftNavigationButtonMouseReleased
        timer.cancel();
        if ((System.currentTimeMillis() - startClickTime) < 500) {
            listener.rotateLeft(22.5);
        }
        startClickTime = 0;
        leftNavigationButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/leftButton.png")));
    }//GEN-LAST:event_leftNavigationButtonMouseReleased

    /**
     * 
     * @param evt Stops rotating up
     */
    private void upNavigationButtonMouseReleased(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_upNavigationButtonMouseReleased
        timer.cancel();
        if ((System.currentTimeMillis() - startClickTime) < 500) {
            listener.rotateUp(22.5);
        }
        startClickTime = 0;
        upNavigationButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/upButton.png")));
    }//GEN-LAST:event_upNavigationButtonMouseReleased

    /**
     * 
     * @param evt Stops rotating down
     */
    private void downNavigationButtonMouseReleased(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_downNavigationButtonMouseReleased
        timer.cancel();
        if ((System.currentTimeMillis() - startClickTime) < 500) {
            listener.rotateDown(22.5);
        }
        startClickTime = 0;
        downNavigationButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/downButton.png")));
    }//GEN-LAST:event_downNavigationButtonMouseReleased

    /**
     * 
     * @param evt Stops zooming in 
     */
    private void plusNavigationButtonMouseReleased(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_plusNavigationButtonMouseReleased
        timer.cancel();
        if ((System.currentTimeMillis() - startClickTime) < 500) {
            listener.zoomIn(30);
        }
        startClickTime = 0;
        plusNavigationButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/plus.png")));
    }//GEN-LAST:event_plusNavigationButtonMouseReleased

    /**
     * 
     * @param evt  Stops zooming out
     */
    private void minusNavigationButtonMouseReleased(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_minusNavigationButtonMouseReleased
        timer.cancel();
        if ((System.currentTimeMillis() - startClickTime) < 500) {
            listener.zoomOut(30);
        }
        startClickTime = 0;
        minusNavigationButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/minus.png")));
    }//GEN-LAST:event_minusNavigationButtonMouseReleased

    /**
     * 
     * @param evt Laoding the .obj file when button pressed
     */
    private void loadModelButtonMouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_loadModelButtonMouseClicked
       loadModel();
    }//GEN-LAST:event_loadModelButtonMouseClicked

    /**
     * 
     * @param evt Design is reacting to mouse movement 
     */
    private void loadModelButtonMouseMoved(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_loadModelButtonMouseMoved
        loadModelButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/loadCanvaClicked.png")));
    }//GEN-LAST:event_loadModelButtonMouseMoved

    /**
     * 
     * @param evt Design is reacting to mouse movement  
     */
    private void loadModelButtonMouseExited(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_loadModelButtonMouseExited
        loadModelButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/loadCanva.png")));
    }//GEN-LAST:event_loadModelButtonMouseExited

    /**
     * 
     * @param evt Enables to rotate down the model when down navigation button is pressed
     */
    private void rightNavigationButton1MousePressed(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_rightNavigationButton1MousePressed
        timer = new Timer();
        startClickTime = System.currentTimeMillis();
        task = new TimerTask() {
            @Override
            public void run() {
                listener.rotateRight(2);
            }
        };
        timer.schedule(task, 500, 100);
        rightNavigationButton1.setIcon(new javax.swing.ImageIcon(getClass().getResource("/rightButtonPressed.png")));
    }//GEN-LAST:event_rightNavigationButton1MousePressed

    /**
     * 
     * @param evt Stops rotating right
     */
    private void rightNavigationButton1MouseReleased(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_rightNavigationButton1MouseReleased
        timer.cancel();
        if ((System.currentTimeMillis() - startClickTime) < 500) {
            listener.rotateRight(22.5);
        }
        startClickTime = 0;
        rightNavigationButton1.setIcon(new javax.swing.ImageIcon(getClass().getResource("/rightButton.png")));
    }//GEN-LAST:event_rightNavigationButton1MouseReleased

    /**
     * 
     * @param evt Position of model on glCanvas is set to starting position
     */
    private void resetButtonMouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_resetButtonMouseClicked
        listener.rotationAndSizeRestart();
    }//GEN-LAST:event_resetButtonMouseClicked

    /**
     * 
     * @param evt Design is reacting to mouse movement  
     */
    private void resetButtonMouseMoved(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_resetButtonMouseMoved
        resetButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/resetButtonPressed.png")));
        resetButton.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
    }//GEN-LAST:event_resetButtonMouseMoved

    /**
     * 
     * @param evt Design is reacting to mouse movement  
     */
    private void resetButtonMouseExited(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_resetButtonMouseExited
        resetButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/resetButton.png")));
    }//GEN-LAST:event_resetButtonMouseExited

    /**
     * 
     * @param evt Changes backround of the canvas into white color
     */
    private void whiteBackroundButtonMouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_whiteBackroundButtonMouseClicked
        listener.setWhiteBackround(true);
        whiteBackroundButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/whiteBackroundCanvasPressed.png")));
        blackBackroundButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/blackBackroundCanvas.png")));
    }//GEN-LAST:event_whiteBackroundButtonMouseClicked

    /**
     * 
     * @param evt Changes backround of the canvas into dark color
     */
    private void blackBackroundButtonMouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_blackBackroundButtonMouseClicked
        listener.setWhiteBackround(false);
        whiteBackroundButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/whiteBackroundCanvas.png")));
        blackBackroundButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/blackBackroundCanvasPressed.png")));
    }//GEN-LAST:event_blackBackroundButtonMouseClicked

    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JLabel blackBackroundButton;
    private javax.swing.JButton downNavigationButton;
    private javax.swing.JLabel jLabel1;
    private javax.swing.JLayeredPane jLayeredPane1;
    private javax.swing.JPanel jPanel1;
    private javax.swing.JButton leftNavigationButton;
    private javax.swing.JLabel loadModelButton;
    private javax.swing.JButton minusNavigationButton;
    private javax.swing.JButton plusNavigationButton;
    private javax.swing.JLabel resetButton;
    private javax.swing.JButton rightNavigationButton1;
    private javax.swing.JButton upNavigationButton;
    private javax.swing.JLabel whiteBackroundButton;
    // End of variables declaration//GEN-END:variables
}
