/*
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License as
 * published by the Free Software Foundation; either version 2 of the
 * License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOUSE. See the GNU
 * General Public License for more details.
 *
 * You should have recieved a copy of the GNU General Public License
 * along with this program; if not write to the Free Software
 * Foundation, inc., 59 Temple Place, Suite 330, Boston MA 02111-1307
 * USA */

/*
 * author  Jonas Forssell
 */
package j3d;
import java.awt.*;
import java.io.*;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.Vector;

import javax.swing.tree.*;
import javax.swing.*;

import java.awt.event.*;

import javax.swing.table.*;
import javax.swing.text.BadLocationException;

import gui.*;

/**
 * Creates a nurbcurve in the shape of an arc (or circle)
 * @author   Jonas Forssell, Yuriy Mikhaylovskiy
 */
public class _BilinearSurface extends _NurbSurface implements Serializable{
  private Canvas3D J3D;
  private PreProcessor PreP;
  private _Point[] p_corner = new _Point[4];
  private Hashtable mat;
  
  JTextField jTextField1, jTextField2, jTextField3, jTextField4, jTextField5, jTextField6, jTextField7;
  JButton jButton2, jButton3, jButton4, jButton5;
  JComboBox jComboBox1, jComboBox2;
  
  
  /**
   * Constructs a NURB surface defined by 4 points to form a bilinear surface.
   * Inputs:
   * 
   * The position of the corner points
   *
   *    ^ v direction
   *    |
   *    ----------------
   *    |p[2]      p[3]|
   *    |              |
   *    |    SRF       |
   *    |              |
   *    |p[0]      p[1]|
   *    -------------------> u direction'''       
   * 
   * @param p_corner			Corner points of the surface
   * @param udiv				Number of line segments used to draw the arc in u-direction
   * @param udiv				Number of line segments used to draw the arc in v-direction
   * @param color				Color of the arc
   * @param element_type		element type to be used for the FE-mesh
   * @param element_material	element material to be used for the FE-mesh
   * @param element_thickness	thickness of the element in the mesh
   */
  public _BilinearSurface(boolean add) {
    super(add);
    mesh_div[0] = 5;
    mesh_div[1] = 5;
  }
  
  private void writeObject(ObjectOutputStream out)  throws IOException{
      out.writeObject(p_corner);
    }
    
  private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException{
      p_corner = (_Point[])in.readObject();
    }

  public void reset() {

      	
        // Generate control points
    	controlPoints = new _CtrlPoint[2][2];

    	for (int i = 0; i < 2; i++)
            for (int j = 0; j < 2; j++)
                controlPoints[i][j] = new _CtrlPoint(p_corner[2 * i + j].x, p_corner[2 * i + j].y, p_corner[2 * i + j].z, 1.0f, Color.GRAY);

        // Generate the knots
        uknots = new float[4];
        vknots = new float[4];
        uorder = 1;
        vorder = 1;

        uknots[0] = 0.0f;
        uknots[1] = 0.0f;
        uknots[2] = 1.0f;
        uknots[3] = 1.0f;

        vknots[0] = 0.0f;
        vknots[1] = 0.0f;
        vknots[2] = 1.0f;
        vknots[3] = 1.0f;

        // Generate geometry & mesh  
        super.reset();

    }

  public String toString(){ return "BLSurface ID="+Id;}

  public MutableTreeNode get_TreeNode(){
    DefaultMutableTreeNode node = new DefaultMutableTreeNode(this);
    
    // Add unique data for this class
    for (int i=0; i < p_corner.length; i++)
        node.add(p_corner[i].get_TreeNode());

    // Add mesh data from _NurbCurve
    node.add(super.get_TreeNode());

    return node;
  }

  public JPanel getEditPanel(Canvas3D j3d, PreProcessor pp){
      this.J3D = j3d;
      this.PreP = pp;

      JPanel jPanel0 = new JPanel();
      JPanel jPanel1 = new JPanel();
      JPanel jPanel2 = new JPanel();
      JPanel jPanel3 = new JPanel();
      JPanel jPanel4 = new JPanel();
      JPanel jPanel5 = new JPanel();
      JPanel jPanel6 = new JPanel();
      JPanel jPanel7 = new JPanel();
      jButton1 = new JButton(add == true?"Add":"Update");
      jButton2 = new JButton("<<");
      jButton3 = new JButton("<<");
      jButton4 = new JButton("<<");
      jButton5 = new JButton("<<");
      jTextField1 = new JTextField((p_corner[0] != null ? p_corner[0].toString() : "") +"",3);
      jTextField2 = new JTextField((p_corner[1] != null ? p_corner[1].toString() : "")+"",3);
      jTextField3 = new JTextField((p_corner[2] != null ? p_corner[2].toString() : "")+"",3);
      jTextField4 = new JTextField((p_corner[3] != null ? p_corner[3].toString() : "")+"",3);
      jTextField6 = new JTextField("" + mesh_div[0]);
      jTextField7 = new JTextField("" + mesh_div[1]);
      
      jPanel0.setLayout(new BoxLayout(jPanel0, BoxLayout.Y_AXIS));
      jPanel0.add(jPanel1);
      	jPanel1.setLayout(new GridLayout(4,3));

      jPanel1.add(new JLabel("LL"), null);
      jPanel1.add(jTextField1, null);
      	jTextField1.setEditable(false);
      jPanel1.add(jButton2, null);
      	jButton2.addActionListener(new java.awt.event.ActionListener() {
          public void actionPerformed(ActionEvent e) {
            jButton2_actionPerformed(e);
          }
        });
        jButton2.addKeyListener(new KeyAdapter() {
            public void keyReleased(KeyEvent e) {
                int c = e.getKeyCode();

                if (c == KeyEvent.VK_ENTER) {
                    jButton2_actionPerformed(null);
                }
            }
        });
      jPanel1.add(new JLabel("LR"), null);
      jPanel1.add(jTextField2, null);
      	jTextField2.setEditable(false);
      jPanel1.add(jButton3, null);
      	jButton3.addActionListener(new java.awt.event.ActionListener() {
      	    public void actionPerformed(ActionEvent e) {
      	        jButton3_actionPerformed(e);
      	    }
      	});
        jButton3.addKeyListener(new KeyAdapter() {
            public void keyReleased(KeyEvent e) {
                int c = e.getKeyCode();

                if (c == KeyEvent.VK_ENTER) {
                    jButton3_actionPerformed(null);
                }
            }
        });
      jPanel1.add(new JLabel("UR"), null);
      jPanel1.add(jTextField3, null);
      	jTextField3.setEditable(false);
      jPanel1.add(jButton4, null);
      	jButton4.addActionListener(new java.awt.event.ActionListener() {
      	    public void actionPerformed(ActionEvent e) {
      	        jButton4_actionPerformed(e);
      	    }
      	});
        jButton4.addKeyListener(new KeyAdapter() {
            public void keyReleased(KeyEvent e) {
                int c = e.getKeyCode();

                if (c == KeyEvent.VK_ENTER) {
                    jButton4_actionPerformed(null);
                }
            }
        });
        jPanel1.add(new JLabel("UL"), null);
        jPanel1.add(jTextField4, null);
        	jTextField4.setEditable(false);
        jPanel1.add(jButton5, null);
        	jButton5.addActionListener(new java.awt.event.ActionListener() {
        	    public void actionPerformed(ActionEvent e) {
        	        jButton5_actionPerformed(e);
        	    }
        	});
            jButton5.addKeyListener(new KeyAdapter() {
                public void keyReleased(KeyEvent e) {
                    int c = e.getKeyCode();

                    if (c == KeyEvent.VK_ENTER) {
                        jButton5_actionPerformed(null);
                    }
                }
            });
      	
      jPanel0.add(jPanel5);
      jPanel5.setLayout(new GridLayout());
      jPanel5.add(new JLabel("U div"), null);
      jPanel5.add(jTextField6, null);
      jTextField6.addKeyListener(new KeyAdapter() {
          public void keyReleased(KeyEvent e) {
              int c = e.getKeyCode();

              if (c == KeyEvent.VK_ENTER) {
                  jTextField7.requestFocus();
                  jTextField7.selectAll();
              }
          }
      });

      jPanel0.add(jPanel6);
      jPanel6.setLayout(new GridLayout());
      jPanel6.add(new JLabel("V div"), null);
      jPanel6.add(jTextField7, null);
      jTextField7.addKeyListener(new KeyAdapter() {
          public void keyReleased(KeyEvent e) {
              int c = e.getKeyCode();

              if (c == KeyEvent.VK_ENTER) {
                  cComboBox1.requestFocus();
              }
          }
      });
            
      jPanel0.add(super.getEditPanel(j3d,pp));
      
      jPanel0.add(jPanel7);
        jPanel7.add(jButton1);
      jButton1.addActionListener(new java.awt.event.ActionListener() {
        public void actionPerformed(ActionEvent e) {
          jButton1_actionPerformed(e);
        }
      });
      jButton1.addKeyListener(new KeyAdapter() {
          public void keyReleased(KeyEvent e) {
              int c = e.getKeyCode();

              if (c == KeyEvent.VK_ENTER) {
                  jButton1_actionPerformed(null);
              }
          }
      });

      jPanel0.validate();

      if (add == true && pp != null)
          pp.message("new Bilinear surface: Select lower left corner point");
      
      return jPanel0;
  }

  public void requestFocus() {
      jButton2.requestFocus();
  }
  
  public void requestAction() {
      if (add == true)
          if (jButton2.hasFocus()) 
              jButton2_actionPerformed(null);
          else if (jButton3.hasFocus()) 
              jButton3_actionPerformed(null);
          else if (jButton4.hasFocus()) 
              jButton4_actionPerformed(null);
          else if (jButton5.hasFocus()) 
              jButton5_actionPerformed(null);
  }
  
  
  void jButton1_actionPerformed(ActionEvent e) {
      _BilinearSurface tmp = this;
      
        if(p_corner[0]==null || p_corner[1]==null ||p_corner[2]==null || p_corner[3]==null) return;
        mesh_div[0] = Integer.parseInt(jTextField6.getText());
        mesh_div[1] = Integer.parseInt(jTextField7.getText());

        tmp.update(e);

        if(add == true) {
            try {
                tmp = (_BilinearSurface)this.clone();
                J3D.add3D(tmp);
              } catch (CloneNotSupportedException e1) {
                  e1.printStackTrace();
              }
            tmp.add = false;
            jButton2.requestFocus();
            
            p_corner = new _Point[4];
        } else
            tmp.reset();

        
        J3D.tree_reset();
        J3D.view_reset();
        J3D.repaint();
    }
  
  void jButton2_actionPerformed(ActionEvent e) {
      Object obj = J3D.getSelectedObject3D();
      if(obj !=null && obj instanceof _Point){
        p_corner[0]=(_Point)obj;
        jTextField1.setText(obj.toString());
        jButton3.requestFocus();
        if (add == true && PreP != null)
            PreP.message("new Bilinear surface: Select lower right corner point");
      }
    }

    void jButton3_actionPerformed(ActionEvent e) {
      Object obj = J3D.getSelectedObject3D();
      if(obj!=null && obj instanceof _Point){
        p_corner[1]=(_Point)obj;
        jTextField2.setText(obj.toString());
        jButton4.requestFocus();
        if (add == true && PreP != null)
            PreP.message("new Bilinear surface: Select upper right corner point");
      }
    }

    void jButton4_actionPerformed(ActionEvent e) {
        Object obj = J3D.getSelectedObject3D();
        if(obj!=null && obj instanceof _Point){
          p_corner[3]=(_Point)obj;
          jTextField3.setText(obj.toString());
          jButton5.requestFocus();
          if (add == true && PreP != null)
              PreP.message("new Bilinear surface: Select upper left corner point");
        }
      }
  
    void jButton5_actionPerformed(ActionEvent e) {
        Object obj = J3D.getSelectedObject3D();
        if(obj!=null && obj instanceof _Point){
          p_corner[2]=(_Point)obj;
          jTextField4.setText(obj.toString());
          jTextField6.requestFocus();
          jTextField6.selectAll();
        }
      }

    public _Object duplicate(Canvas3D out){ 
        _BilinearSurface o = null;
        try {
          o = (_BilinearSurface)this.clone();
      } catch (CloneNotSupportedException e) {
          e.printStackTrace();
      }
      
      for (int i=0; i<4; i++)
          o.p_corner[i] = (_Point)p_corner[i].duplicate(out,add);
     
      out.add3D(o);
        
      return o;
    }
    
    
    public void transform3D(Matrix3D t){
        if(!selected)return;
        super.transform3D(t);
        for (int i=0; i<4; i++) {
          p_corner[i].Select("");
          p_corner[i].transform3D(t);
          p_corner[i].Select(null);
          p_corner[i].setProcessed(true);          
        }          
        reset();
      }    
    

    public void addSelectedObjects(Vector v) {
        if (selected) v.add(this);
        super.addSelectedObjects(v);
    }

   
}

