// @topic S-0330-14-15-10 Java MVC JTable Demo
// @brief class WindowMainApp extends JFrame<br />download netbeans <a href="http://www.c-jump.com/bcc/c260c/c260samples15S/Java/Wk09_MVC_JTable/WindowMainApp.form"><tt>WindowMainApp.form</tt></a>

package gui_demo;

import java.awt.Font;
import java.util.ArrayList;
import javax.swing.table.JTableHeader;
import javax.swing.table.TableColumn;

public class WindowMainApp extends javax.swing.JFrame {

    //------------------------------
    // data
    //------------------------------
    private ControllerDemo controller;

    //------------------------------
    // constructors
    //------------------------------
    /**
     * Creates new form WindowMainApp
     */
    public WindowMainApp(ControllerDemo controller) {
        this.controller = controller;
        initComponents();
        this.setTitle("MVC JTable Demo");
        // change table header font:
        JTableHeader header = tblSimulation.getTableHeader();
        header.setFont(
                new Font(
                        "SansSerif",
                        Font.BOLD | Font.ITALIC,
                        14/*size*/
                )
        );
    }

    /**
     * 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.
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        pnlMain = new javax.swing.JPanel();
        btnPopulateTable = new javax.swing.JButton();
        jScrollPane1 = new javax.swing.JScrollPane();
        tblSimulation = new javax.swing.JTable();
        btnSaveScenario = new javax.swing.JButton();
        btnRunSimulation = new javax.swing.JButton();
        btnStopSimulation = new javax.swing.JButton();

        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);

        btnPopulateTable.setText("Populate Table");
        btnPopulateTable.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                btnPopulateTableActionPerformed(evt);
            }
        });

        tblSimulation.setModel(new javax.swing.table.DefaultTableModel(
            new Object [][] {

            },
            new String [] {

            }
        ));
        jScrollPane1.setViewportView(tblSimulation);

        btnSaveScenario.setText("Save Scenario");
        btnSaveScenario.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                btnSaveScenarioActionPerformed(evt);
            }
        });

        btnRunSimulation.setText("Run");
        btnRunSimulation.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                btnRunSimulationActionPerformed(evt);
            }
        });

        btnStopSimulation.setText("Stop");
        btnStopSimulation.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                btnStopSimulationActionPerformed(evt);
            }
        });

        javax.swing.GroupLayout pnlMainLayout = new javax.swing.GroupLayout(pnlMain);
        pnlMain.setLayout(pnlMainLayout);
        pnlMainLayout.setHorizontalGroup(
            pnlMainLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(pnlMainLayout.createSequentialGroup()
                .addContainerGap()
                .addGroup(pnlMainLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 411, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addGroup(pnlMainLayout.createSequentialGroup()
                        .addComponent(btnPopulateTable)
                        .addGap(18, 18, 18)
                        .addComponent(btnSaveScenario)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                        .addComponent(btnRunSimulation)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                        .addComponent(btnStopSimulation)))
                .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
        );
        pnlMainLayout.setVerticalGroup(
            pnlMainLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, pnlMainLayout.createSequentialGroup()
                .addContainerGap()
                .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 227, Short.MAX_VALUE)
                .addGap(18, 18, 18)
                .addGroup(pnlMainLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(btnPopulateTable)
                    .addComponent(btnSaveScenario)
                    .addComponent(btnRunSimulation)
                    .addComponent(btnStopSimulation))
                .addGap(18, 18, 18))
        );

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
        getContentPane().setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addComponent(pnlMain, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addGap(0, 10, Short.MAX_VALUE))
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addComponent(pnlMain, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addGap(0, 3, Short.MAX_VALUE))
        );

        pack();
    }// </editor-fold>//GEN-END:initComponents

    private void btnPopulateTableActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnPopulateTableActionPerformed
        // change header font:
        JTableHeader header = tblSimulation.getTableHeader();
        header.setFont(
                new Font(
                        "SansSerif",
                        Font.BOLD | Font.ITALIC,
                        18/*size*/
                )
        );
        // configure column names:
        int columns = 4;
        String[] columnNames = new String[columns];
        columnNames[0] = "A";
        columnNames[1] = "B";
        columnNames[2] = "Floor Occupancy";
        columnNames[3] = "";

        // pretend that we have an array of floor objects:
        ArrayList<Floor> floors = new ArrayList<>();
        floors.add(new Floor("P"));
        floors.add(new Floor("L"));
        floors.add(new Floor("2"));
        floors.add(new Floor("3"));
        floors.add(new Floor("4"));

        // populate table rows
        int rows = 5;
        Object[][] tableContent = new Object[rows][columns];
        for (int row = tableContent.length - 1; row > -1; --row) {
            Floor floor = floors.get(floors.size() - row - 1);
            tableContent[row][tableContent[row].length - 1]
                    = floor.getLabel();
        }

        // set actual data:
        tblSimulation.setModel(
                new javax.swing.table.DefaultTableModel(
                        tableContent,
                        columnNames
                )
        );

        // adjust column sizes
        TableColumn column = null;
        int numberOfElevators = 2;
        columns = tblSimulation.getColumnModel().getColumnCount();
        //System.out.println("debug columns == "+ columns);
        for (int idx = 0; idx < columns; ++idx) {
            column = tblSimulation.getColumnModel().getColumn(idx);
            if (idx < numberOfElevators) {
                column.setPreferredWidth(25/*pixels*/);
                //System.out.println("debug elevator == "+ idx);
            } else if (idx == columns - 1/*last column*/) {
                column.setPreferredWidth(20/*pixels*/);
                //System.out.println("debug last column == "+ idx);
            } else {
                column.setPreferredWidth(145/*pixels*/);
                //System.out.println("debug the rest == "+ idx);
            }
        }

        // update individual cells:
        int rowIndex = 0;
        int columnIndex = 1;
        tblSimulation.getModel().setValueAt(
                new Integer(5)/*content*/, rowIndex, columnIndex);

        rowIndex = 1;
        columnIndex = 0;
        tblSimulation.getModel().setValueAt(
                new Integer(3)/*content*/, rowIndex, columnIndex);

        rowIndex = 0;
        columnIndex = 2;
        tblSimulation.getModel().setValueAt(
                "occupancy " + 12/*content*/, rowIndex, columnIndex);
    }//GEN-LAST:event_btnPopulateTableActionPerformed

    private void btnSaveScenarioActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnSaveScenarioActionPerformed
        controller.saveScenario(
                6/*numberOfFloors*/,
                3/*numberOfElevators*/
        );
        configureBuildingDisplay();
        update();
    }//GEN-LAST:event_btnSaveScenarioActionPerformed

    private void btnRunSimulationActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnRunSimulationActionPerformed
        controller.runSimulation();
    }//GEN-LAST:event_btnRunSimulationActionPerformed

    private void btnStopSimulationActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnStopSimulationActionPerformed
        controller.stopSimulation();
    }//GEN-LAST:event_btnStopSimulationActionPerformed

    /**
     * @param args the command line arguments
     */
    public static void main(String args[]) {
        /* Set the Nimbus look and feel */
        //<editor-fold defaultstate="collapsed" desc=" Look and feel setting code (optional) ">
        /* If Nimbus (introduced in Java SE 6) is not available, stay with the default look and feel.
         * For details see http://download.oracle.com/javase/tutorial/uiswing/lookandfeel/plaf.html 
         */
        try {
            for (javax.swing.UIManager.LookAndFeelInfo info : javax.swing.UIManager.getInstalledLookAndFeels()) {
                if ("Nimbus".equals(info.getName())) {
                    javax.swing.UIManager.setLookAndFeel(info.getClassName());
                    break;
                }
            }
        } catch (ClassNotFoundException ex) {
            java.util.logging.Logger.getLogger(WindowMainApp.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        } catch (InstantiationException ex) {
            java.util.logging.Logger.getLogger(WindowMainApp.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        } catch (IllegalAccessException ex) {
            java.util.logging.Logger.getLogger(WindowMainApp.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        } catch (javax.swing.UnsupportedLookAndFeelException ex) {
            java.util.logging.Logger.getLogger(WindowMainApp.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        }
        //</editor-fold>

        // Create the controller object
        final ControllerDemo controller = new ControllerDemo();

        // create and start new thread:
        ThreadAnimation thp = new ThreadAnimation(controller);
        Thread th = new Thread(thp);
        th.start();

        // Execute initialization of all required buseness objects
        controller.initUseCase();

        /* Create and display the form */
        java.awt.EventQueue.invokeLater(new Runnable() {
            public void run() {
                // Create the window
                // Let controller know the window object
                // Visualize the window
                WindowMainApp mainWindow = new WindowMainApp(controller);
                controller.setWindow(mainWindow);
                mainWindow.setVisible(true);
            }
        });
    }//main

    public void configureBuildingDisplay() {
        int numberOfElevators = controller.getScenario().getNumberOfElevators();
        int columns
                = 2 // floor occupancy and floor label columns
                + // each elevator gets its own column in the grid:
                numberOfElevators;
        String[] columnNames = new String[columns];
        for (int idx = 0; idx < columns; ++idx) {
            if (idx < numberOfElevators) {
                // this column represents the elevator shaft
                columnNames[idx]
                        = ElevatorBank.GetInstance().getElevator(idx).getLabel();
            } else if (idx == columns - 1) {
                // last column is the floor label
                columnNames[idx] = "Floor#";
            } else {
                // floor occupancy
                columnNames[idx] = "Visitor occupancy";
            }
        }
        // populate table rows
        int numberOffloors = controller.getScenario().getNumberOfFloors();
        Object[][] tableContent = new Object[numberOffloors][columns];
        for (int row = tableContent.length - 1; row > -1; --row) {
            ArrayList<Floor> floors = ElevatorBank.GetInstance().getFloors();
            // to traverse the floors top-down, calculate index of the
            // floor as follows:
            Floor floor = floors.get(floors.size() - row - 1);
            // update last column (floor label)
            tableContent[row][tableContent[row].length - 1]
                    = floor.getLabel();
        }
        // pass the data to the table gadget:
        tblSimulation.setModel(
                new javax.swing.table.DefaultTableModel(
                        tableContent,
                        columnNames
                )
        );
    }//configureBuildingDisplay

    public void update() {
        // controller calls this method to
        // update the elevator-floor view
        // save scenario also calls this
        // to visualize latest config
        ArrayList<Elevator> elevators = ElevatorBank.GetInstance().getElevators();
        ArrayList<Floor> floors = ElevatorBank.GetInstance().getFloors();
        int columnIndex = 0; // first elevator shown in the leftmost table column
        for ( Elevator elevator : elevators ) {
            ;
            // update elevator location:
            int rowIndex = floors.size() - elevator.getFloor() - 1;
            tblSimulation.getModel().setValueAt(
                elevator.getLabel()+rowIndex+" "+columnIndex/*content*/, 0, 3
            );
            tblSimulation.getModel().setValueAt(
                elevator.getLabel()+rowIndex/*content*/, rowIndex, columnIndex
            );
            // clear all locations:
            for ( int idx = 0; idx < floors.size(); ++ idx ) {
                if ( idx != rowIndex ) {
                    tblSimulation.getModel().setValueAt(
                        null/*content*/, idx, columnIndex
                    );
                }
            }
            ++columnIndex; // next elevator shown in the next table column
        }
    }//update

    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JButton btnPopulateTable;
    private javax.swing.JButton btnRunSimulation;
    private javax.swing.JButton btnSaveScenario;
    private javax.swing.JButton btnStopSimulation;
    private javax.swing.JScrollPane jScrollPane1;
    private javax.swing.JPanel pnlMain;
    private javax.swing.JTable tblSimulation;
    // End of variables declaration//GEN-END:variables
}