package gui;

import java.awt.*;
import java.io.File;
import java.lang.reflect.Method;

import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JSplitPane;

import controller.Controller;
import gui.visualgraph.VisualGraphPanel;

/**
 * The {@code JFrame} which contains all panels.
 * 
 * @author Michael
 *
 */
public class ProgramFrame extends JFrame {

    private static final long serialVersionUID = 5047834266753718967L;

    private JPanel contentPane;
    private InputPanel inputPanel;
    private ControlPanel controlPanel;
    private StatePanelOpen statePanelOpen;
    private StatePanelClosed statePanelClosed;
    private VisualGraphPanel visualGraphPanel;
    private boolean isStatePanelOpen;
    private static final Dimension MIN_SIZE = new Dimension(1200, 800);
    private static final Rectangle STANDARD_BOUNDS = new Rectangle(0, 0, 1600, 800);

    /**
     * Creates a {@code JFrame} and its content. Sets theLayout of the
     * ContentPane.
     * 
     * @param ctrl
     *            the {@code Controller} with which the {@code actionListeners}
     *            will correspond
     * 
     * @see Controller
     * @see java.awt.event.ActionListener
     */

    public ProgramFrame(Controller ctrl) {
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        
        setTitle("Data-Flow Analysis");
        
        setBounds(STANDARD_BOUNDS);
        setExtendedState(getExtendedState() | Frame.MAXIMIZED_BOTH);
        setMinimumSize(MIN_SIZE);
        contentPane = new JPanel();

        contentPane.setLayout(new BorderLayout(0, 0));
        setContentPane(contentPane);

        inputPanel = new InputPanel(ctrl);

        JPanel centerPan = new JPanel();
        contentPane.add(centerPan, BorderLayout.CENTER);
        centerPan.setLayout(new BorderLayout(0, 0));
        
        JSplitPane inputGraphSplit = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT,  inputPanel, centerPan);
        inputGraphSplit.setDividerSize(5);
        inputGraphSplit.setDividerLocation(375);
        contentPane.add(inputGraphSplit, BorderLayout.CENTER);
        
        visualGraphPanel = ctrl.getVisualGraphPanel();
        centerPan.add(visualGraphPanel, BorderLayout.CENTER);

        controlPanel = new ControlPanel(ctrl);
        centerPan.add(controlPanel, BorderLayout.SOUTH);

        statePanelOpen = new StatePanelOpen(this);
        contentPane.add(statePanelOpen, BorderLayout.EAST);

        isStatePanelOpen = true;

        statePanelClosed = new StatePanelClosed(this);

        if (System.getProperty("os.name").toLowerCase().contains("mac") && getWindows().length != 0) {
            enableMacOSFullscreen(getWindows()[0]);
        }

        setIconImage(IconLoader.loadIcon("./icons/app-icon.png", 1).getImage());
    }

    /**
     * This method will switch between the {@code StatePanelOpen} and the
     * {@code StatePanelClosed}. Only one of them will be shown at a time.
     * 
     * @see StatePanelOpen
     * @see StatePanelClosed
     */
    public void switchStatePanel() {
        if (isStatePanelOpen) {
            remove(statePanelOpen);
            add(statePanelClosed, BorderLayout.EAST);
            isStatePanelOpen = false;
        } else {
            remove(statePanelClosed);
            add(statePanelOpen, BorderLayout.EAST);
            isStatePanelOpen = true;
        }

        revalidate();
        repaint();
    }

    /**
     * This method will return the {@code InputPanel}.
     * 
     * @return The {@code InputPanel}.
     * @see InputPanel
     */
    public InputPanel getInputPanel() {
        return inputPanel;
    }

    /**
     * This method will return the {@code ControlPanel}.
     * 
     * @return The {@code ControlPanel}.
     * @see ControlPanel
     */
    public ControlPanel getControlPanel() {
        return controlPanel;
    }

    /**
     * This method will return the {@code StatePanelOpen}.
     * 
     * @return The {@code StatePanelOpen}.
     * @see StatePanelOpen
     */
    public StatePanelOpen getStatePanelOpen() {
        return statePanelOpen;
    }
    
    /**
     * Opens a {@code JFileChooser}, so the user can set the path to his JDK.
     * 
     * @return The path chosen by the user.
     * @see JFileChooser
     */
    public File getCompilerPath() {
        JFileChooser pathChooser = new JFileChooser(System.getProperty("java.home"));
        pathChooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
        int returnVal = JFileChooser.CANCEL_OPTION;
        while (returnVal == JFileChooser.CANCEL_OPTION || returnVal == JFileChooser.ERROR_OPTION) {
            returnVal = pathChooser.showOpenDialog(this);
        }
        return pathChooser.getSelectedFile();
    }

    @SuppressWarnings({"unchecked", "rawtypes"})
    private static void enableMacOSFullscreen(Window window) {
        try {
            Class util = Class.forName("com.apple.eawt.FullScreenUtilities");
            Class params[] = new Class[]{Window.class, Boolean.TYPE};
            Method method = util.getMethod("setWindowCanFullScreen", params);
            method.invoke(util, window, true);
        } catch (Exception ex) {
            System.err.println("Could not enable macOS fullscreen capability. Fullscreen mode will be unavailable. \n"
              + ex.getMessage());
        }
    }
}

@@ -2553,24 +2553,133 @@
 sed(this);%0A%0A
+        Image icon = IconLoader.loadIcon(%22./icons/app-icon.png%22, 1).getImage();%0A        setIconImage(icon);%0A%0A
         if (
@@ -2802,16 +2802,30 @@
 llscreen
+AndSetDockIcon
 (getWind
@@ -2832,16 +2832,22 @@
 ows()%5B0%5D
+, icon
 );%0A     
@@ -2854,90 +2854,8 @@
    %7D
-%0A%0A        setIconImage(IconLoader.loadIcon(%22./icons/app-icon.png%22, 1).getImage());
 %0A   
@@ -4905,16 +4905,30 @@
 llscreen
+AndSetDockIcon
 (Window 
@@ -4933,16 +4933,28 @@
 w window
+, Image icon
 ) %7B%0A    
@@ -5240,118 +5240,530 @@
 e);%0A
-        %7D catch (Exception ex) %7B%0A            System.err.println(%22Could not enable macOS fullscreen capability.
+%0A            Class application = Class.forName(%22com.apple.eawt.Application%22);%0A            Object applicationObject = application.newInstance().getClass().getMethod(%22getApplication%22)%0A                    .invoke(null);%0A            applicationObject.getClass().getMethod(%22setDockIconImage%22, java.awt.Image.class)%0A                    .invoke(applicationObject, icon);%0A        %7D catch (Exception ex) %7B%0A            ex.printStackTrace();%0A            System.err.println(%22Failed to set macOS specific visual attributes. App icon or
  Ful
@@ -5774,17 +5774,16 @@
 een 
-m
+M
 ode 
-will
+may
  be 
@@ -5794,17 +5794,16 @@
 ailable.
- 
 %5Cn%22%0A    

Make dock icon show up on macOS