/*  PointPanel.java
 *
 *  Created on August 17, 2005, 12:34 PM
 *
 *  Here we contain all that is needed to store 
 *  points and display them.
 *
 *  Author: Michael A. Piskuric (2537405) Summer 2005
 */

import Robot.*;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.util.*;
import java.io.*;

public class PointPanel extends JPanel implements ActionListener {
    
    private TeachVAL    parent;             // parent window
    private LinkedList  thePoints = new LinkedList();   // linked list of points
    private int         numPoints = 0;                  // number of points
    private JButton     addPoint,delPoint,editPoint,showLoc,home;    
    private JScrollPane scrollPane;
    private JTable      table;
    
    // create new instance of pointPanel and add it to the parent window
    public PointPanel(TeachVAL p) {
        parent = p;
        initComponents();
        addPoint.addActionListener(this);
        delPoint.addActionListener(this);
        editPoint.addActionListener(this);
        showLoc.addActionListener(this);
        home.addActionListener(this);
        toggleButtons(false);
        parent.add(this);        
    }
    
    // toggle the 4 buttons on or off
    public void toggleButtons(boolean onoff) {
        addPoint.setEnabled(onoff);
        editPoint.setEnabled(onoff);
        delPoint.setEnabled(onoff);
        showLoc.setEnabled(onoff);
        home.setEnabled(onoff);
    }
    
    // clear the points from memory
    public void clearPoints() {
        thePoints.clear();
        redrawTable();
    }
    
    // get all the available points
    public LinkedList getAllPoints() {
        return thePoints;
    }
    
    // get a specific point
    public Location getPoint(String name) {
        Location temp = null;
        Iterator it = thePoints.iterator();
        while(it.hasNext()) {
            temp = (Location)it.next();
            if(temp.getName().compareTo(name) == 0) 
                break;
        }
        return temp;
    }
    
    // add a new point given a location
    public void addNewPoint(Location loc) {
        if(loc.isValid()) {
            thePoints.add(loc);  
            numPoints = thePoints.size();
            writeTableRow(loc, numPoints-1);
            parent.getStatusBar().setText("Point added successfully");
        }
        else new TVException(loc.getError());
    }
    
    // write the data to the the table row by row
    private void writeTableRow(Location loc, int row){
        table.getModel().setValueAt(loc.getName(),row,0);
        table.getModel().setValueAt(loc.getX(),row,1);
        table.getModel().setValueAt(loc.getY(),row,2);
        table.getModel().setValueAt(loc.getZ(),row,3);
        table.getModel().setValueAt(loc.getPitch(),row,4);
        table.getModel().setValueAt(loc.getRoll(),row,5);            
    }
    
    // this method was borrowed from http://www.cs.wisc.edu/~shavlik/cs760/AgentWorld/Utils.java-sample
    public String truncate(double d){ 
        int decimals = 2;
        String  str   = Double.toString(d);
        int     index = str.indexOf(".");
        if (index < 0) return str.concat(".0");
    
        int indexE = indexOfIgnoreCase(str, "e", index);
        if (indexE > 0)
            return str.substring(0, Math.min(indexE, index + decimals + 1)) + "e" + Integer.valueOf(str.substring(indexE + 1));
        else 
            return str.substring(0, Math.min(str.length(), index + decimals + 1));        
    }
    
    // this method was borrowed from http://www.cs.wisc.edu/~shavlik/cs760/AgentWorld/Utils.java-sample
    private static int indexOfIgnoreCase(String str, String query, int fromIndex){ 
        int qlength = query.length();
        int max = (str.length() - qlength);
    
        test:
        for(int i = ((fromIndex < 0) ? 0 : fromIndex); i <= max ; i++){  
            int k = 0, j = i, n = qlength;
            char schar, qchar;
            while (n-- > 0){
                schar = str.charAt(j++);
                qchar = query.charAt(k++);
                if ((schar != qchar) &&(Character.toLowerCase(schar) != Character.toLowerCase(qchar)))
                continue test;
            }
            return i;
        }
    return -1;
  }
    
    // this removes a specific point from memory
    public void removePoint(String name) {
        Iterator it = thePoints.iterator();
        while(it.hasNext()) {           
            if(((Location)it.next()).getName().compareTo(name) == 0){
                it.remove();
                parent.getStatusBar().setText("Point removed sucessfully.");
            }            
        }
        numPoints = thePoints.size();
        redrawTable();
    }
    
    // redraw the table after a point was removed or edited
    private void redrawTable() {
        for(int i=0; i<table.getModel().getRowCount(); i++) 
            for(int j=0; j<table.getModel().getColumnCount(); j++) 
                table.getModel().setValueAt(null,i,j);
            
        Iterator it = thePoints.iterator();
        int counter = 0;
        while(it.hasNext()) {
            writeTableRow((Location)it.next(), counter);
            counter++;
        }
    }
    
    // initilize the components of the panel
    private void initComponents() {
        addPoint = new javax.swing.JButton();
        editPoint = new javax.swing.JButton();
        delPoint = new javax.swing.JButton();
        showLoc = new javax.swing.JButton();
        home = new javax.swing.JButton();
        scrollPane = new javax.swing.JScrollPane();
        table = new javax.swing.JTable();

        setLayout(null);

        setBorder(new javax.swing.border.TitledBorder("Available Points"));
        setPreferredSize(new Dimension((int)(parent.getWidth()-20),(int)((parent.getHeight()-80)*.2)));
        addPoint.setText("Add New Point");
        add(addPoint);
        addPoint.setBounds(870, 20, 130, 20);

        editPoint.setText("Edit Point");
        add(editPoint);
        editPoint.setBounds(870, 40, 130, 20);        
        
        delPoint.setText("Delete Point(s)");
        add(delPoint);
        delPoint.setBounds(870, 60, 130, 20);

        showLoc.setText("Where am I?");
        add(showLoc);
        showLoc.setBounds(870, 80, 130, 20);
        
        home.setText("Home Robot");
        add(home);
        home.setBounds(870, 100, 130, 20);
        
        scrollPane.setBackground(new java.awt.Color(255, 255, 255));
        scrollPane.setBorder(new javax.swing.border.LineBorder(new java.awt.Color(0, 0, 0)));
        scrollPane.setHorizontalScrollBarPolicy(javax.swing.ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
        scrollPane.setDoubleBuffered(true);
        table.setModel(new javax.swing.table.DefaultTableModel(
            new Object [][] {
                {null, null, null, null, null, null},
                {null, null, null, null, null, null},
                {null, null, null, null, null, null},
                {null, null, null, null, null, null},
                {null, null, null, null, null, null},
                {null, null, null, null, null, null},
                {null, null, null, null, null, null},
                {null, null, null, null, null, null},
                {null, null, null, null, null, null},
                {null, null, null, null, null, null},
                {null, null, null, null, null, null},
                {null, null, null, null, null, null},
                {null, null, null, null, null, null},
                {null, null, null, null, null, null},
                {null, null, null, null, null, null},
                {null, null, null, null, null, null},
                {null, null, null, null, null, null},
                {null, null, null, null, null, null},
                {null, null, null, null, null, null},
                {null, null, null, null, null, null}
            },
            new String [] {
                "Name", "X", "Y", "Z", "Pitch", "Roll"
            }
        ) {
            Class[] types = new Class [] {
                java.lang.String.class, java.lang.Double.class, java.lang.Double.class, java.lang.Double.class, java.lang.Double.class, java.lang.Double.class
            };
            boolean[] canEdit = new boolean [] {
                false, false, false, false, false, false
            };

            public Class getColumnClass(int columnIndex) {
                return types [columnIndex];
            }

            public boolean isCellEditable(int rowIndex, int columnIndex) {
                return canEdit [columnIndex];
            }
        });
        table.setAutoResizeMode(javax.swing.JTable.AUTO_RESIZE_ALL_COLUMNS);
        scrollPane.setViewportView(table);

        add(scrollPane);
        scrollPane.setBounds(20, 20, 840, 98);
    }
    
    private Location whereAmI(){
        parent.getPort().read();
        int data[] = parent.getPort().getAllData();
        if(data[0] == parent.getPort().SUCCESSFUL) {
            int b = 0 + data[1];
            int s = -499 + data[2];
            int e = 1165 + data[3];
            int rw = 384 + data[4];
            int lw = 384 + data[5];
            int g = 0 + data[6];
            return new Location(b,s,e,rw,lw,g,null);
        }
        return null;
    }
    
    // this is the button listener the does the corrent 
    // things when the button is pressed
    public void actionPerformed(ActionEvent e) {
        JButton temp = (JButton)e.getSource();
        parent.tempClosePort();
        parent.reOpenPort();        
        if(temp.getText() == "Add New Point"){
            new LocationDialog(parent,temp.getText());	
        }
        else if(temp.getText() == "Delete Point(s)"){
            int[] whatRows = table.getSelectedRows();
            if(whatRows.length > 0) {
                for(int i=0; i<whatRows.length; i++) {
                    String theLoc = (String)(table.getModel().getValueAt(whatRows[i],0));
                    if (theLoc != null && parent.confirm("Do you want to delete " + theLoc + "?")) removePoint(theLoc);
                }
            }
        }
        else if(temp.getText() == "Edit Point"){
            int[] whatRows = table.getSelectedRows();
            if(whatRows.length == 1) {
                String theLoc = (String)(table.getModel().getValueAt(whatRows[0],0));
                if (theLoc != null) {
                    parent.getMenu().setRun(false);
                    new LocationDialog(parent,getPoint(theLoc));                  
                }
            }
        }
        else if(temp.getText() == "Where am I?"){
                Location tmp = whereAmI();                
                parent.getCompiler().clear();
                parent.getCompiler().write("X: " + truncate(tmp.getX()));
                parent.getCompiler().write("Y: " + truncate(tmp.getY()));
                parent.getCompiler().write("Z: " + truncate(tmp.getZ()));
                parent.getCompiler().write("Pitch: " + truncate(tmp.getPitch()));
                parent.getCompiler().write("Roll: " + truncate(tmp.getRoll()));
        }
        else if(temp.getText() == "Home Robot"){
            Location tmp = whereAmI();
            int steps[] = tmp.move(Microbot.HOME);
            parent.getPort().grip(240);
            parent.getPort().step(240,steps[0],steps[1],steps[2],steps[3],steps[4],0);
       
        }
    }
}
