package shapeUtil;

import java.awt.*;
import java.awt.geom.*;
import java.awt.event.*;
import java.util.*;
import javax.swing.*;
import javax.swing.event.*;
import javax.swing.border.*;
import javax.swing.border.Border.*;
import DrawTop.*;
import shape.*;
import geomExtension.*;
import menu.*;
import util.*;

public class Translate extends JDialog implements ConnectionListener{
    TranslateAction action=null;
    JLabel messageLabel=null;
    Dimension panelSize=new Dimension(220, 44);
    JRadioButton pixelButton=null;
    JRadioButton mmButton=null;
    JSpinner[] translateSpinners=new JSpinner[2];
    SpinnerNumberModel[] translateSpinnerModels=new SpinnerNumberModel[2];
    JCheckBox checkBox=null;
    JRadioButton copyButton=null;
    JButton goButton=null;
    JButton cancelButton=null;
    Vector shapesVector=new Vector();
    Vector2D translateVec=new Vector2D(0d,0d);
    Vector twoPointsVector=new Vector();
    int debug=0;
    
    public Translate(){
        super(ObjectTable.getDrawMain(), "translate");
        this.setName("translate");  
        this.action=new TranslateAction(this);
        this.createDialog();
    }
    
    public void createDialog(){
        //Component owner=this.getOwner();
        //Point centerP=new Point(owner.getX()+10, owner.getY()+80);
        //this.setLocation(centerP);
        
        this.addWindowListener(this.action);
        Container contentPane=this.getContentPane();
        Box box=Box.createVerticalBox();
        contentPane.add(box);

    //MessagePanel
        JPanel messagePanel=new JPanel();
        messagePanel.setLayout(new FlowLayout(FlowLayout.LEADING));
        this.messageLabel=new JLabel(" ");
        messagePanel.add(this.messageLabel);
        
    //uni Panel   
        JPanel unitPanel=new JPanel();
        unitPanel.setPreferredSize(new Dimension(100,44));
        TitledBorder frameBorder=BorderFactory.createTitledBorder("unit of length");
        GridLayout unitPanelLayout=new GridLayout(1,2);
        unitPanelLayout.setHgap(20);
        unitPanelLayout.setVgap(5);
        unitPanel.setLayout(unitPanelLayout);
        unitPanel.setBorder(frameBorder);
        ButtonGroup group = new ButtonGroup();
        this.pixelButton = new JRadioButton("pixel");
        this.mmButton = new JRadioButton("mm");
        group.add(this.mmButton);
        group.add(this.pixelButton);
        this.pixelButton.setActionCommand("pixel");
        this.mmButton.setActionCommand("mm");
        this.pixelButton.addActionListener(this.action);
        this.mmButton.addActionListener(this.action);
        unitPanel.add(mmButton);
        unitPanel.add(pixelButton);
        this.mmButton.setSelected(true);
        
    //translat ePanel   
        JPanel translatePanel=new JPanel();
        frameBorder=BorderFactory.createTitledBorder("translate x,y");
        frameBorder.setTitleColor(Color.BLACK);
        frameBorder.setTitleFont(MenuConstants.MenuFont);
        translatePanel.setBorder(frameBorder);
        GridLayout translatePanelLayout=new GridLayout(2,1);
        translatePanelLayout.setHgap(20);
        translatePanelLayout.setVgap(5);
        translatePanel.setLayout(translatePanelLayout);
      // xy panel
        JPanel xyPanel=new JPanel();
        GridLayout xyPanelLayout=new GridLayout(1,2);
        xyPanelLayout.setHgap(20);
        xyPanelLayout.setVgap(5);
        xyPanel.setLayout(xyPanelLayout);
        JPanel[] xyPanels=new JPanel[2];
        String[] xyLabel={"x: ", "y: "};
        //TranslateSpinnerListener 
        TranslateSpinnerListener spinnerListener=new TranslateSpinnerListener(this);
        for(int i=0;i<2;i++){
            xyPanels[i]=new JPanel();
            xyPanels[i].setLayout(new BoxLayout(xyPanels[i],BoxLayout.X_AXIS));
            JLabel label=new JLabel(xyLabel[i]);
            xyPanels[i].add(label);
            this.translateSpinnerModels[i]=new SpinnerNumberModel(0d, -1000d, 1000d, 1d);
            this.translateSpinners[i]=new JSpinner(translateSpinnerModels[i]);
            this.translateSpinners[i].addChangeListener(spinnerListener);
            xyPanels[i].add(this.translateSpinners[i]);
            xyPanel.add(xyPanels[i]);
        }
        translatePanel.add(xyPanel);
        
      // checkbox panel
        JPanel checkBoxPanel=new JPanel();
        checkBoxPanel.setLayout(new BoxLayout(checkBoxPanel,BoxLayout.X_AXIS));
        JLabel checBoxLabel=new JLabel(": click two points ");
        this.checkBox=new JCheckBox();
        checkBoxPanel.add(this.checkBox);
        checkBoxPanel.add(checBoxLabel);
        this.checkBox.addActionListener(this.action);
        this.checkBox.setActionCommand("click");
        translatePanel.add(checkBoxPanel);

     //Copy Panel
        JPanel copyPanel=new JPanel();
        //copyPanel.setPreferredSize(new Dimension(220, 10));
        frameBorder=BorderFactory.createTitledBorder("copy");
        copyPanel.setBorder(frameBorder);
        GridLayout copyPanelLayout=new GridLayout(1,2);
        copyPanel.setLayout(copyPanelLayout);
        ButtonGroup copyGroup = new ButtonGroup();
        this.copyButton = new JRadioButton("yes");
        JRadioButton noCopyButton = new JRadioButton("no");
        copyGroup.add(this.copyButton);
        this.copyButton.setSelected(true);
        copyGroup.add(noCopyButton);
        copyPanel.add(this.copyButton);
        copyPanel.add(noCopyButton);

    //Go, Cancel Button    
        JPanel buttonPanel=new JPanel();
        //buttonPanel.setPreferredSize(this.panelSize);
        this.goButton=new JButton("GO !");
        this.cancelButton=new JButton("Cancel");
        this.goButton.setEnabled(false);
        this.goButton.setActionCommand("Go");
        this.cancelButton.setActionCommand("Cancel");
        this.goButton.addActionListener(action);
        this.cancelButton.addActionListener(action);
        buttonPanel.add(this.goButton);
        buttonPanel.add(this.cancelButton);
        
// layout the dialog
        box.add(Box.createVerticalStrut(5));
        box.add(messagePanel);
        box.add(Box.createVerticalStrut(5));
        box.add(unitPanel);
        box.add(Box.createVerticalStrut(5));
        box.add(translatePanel);
        box.add(Box.createVerticalStrut(5));
        box.add(copyPanel);
        box.add(Box.createVerticalStrut(5));
        box.add(buttonPanel);
    }
    
    public void showDialog(){
        Component owner=this.getOwner();
        Point centerP=new Point(owner.getX()+owner.getSize().width-250, owner.getY()+100);
        this.setLocation(centerP);
        this.pack();
        this.setVisible(true);
 //set Receiver
      //--------------------------------------------------//  
      // SelectionLS selectionLS=ObjectTable.getSelectionLS();
      // selectionLS.addSelectionListener(this);
      //--------------------------------------------------//
        ContainerManager containerManager=ObjectTable.getContainerManager("");
        ShapeContainer[] containers=containerManager.getSelectedContainers();
        int size=0;
        if(containers!=null) size=containers.length;
        if(size>0){
            this.shapesVector.clear();
            for(int i=0;i<size;i++) this.shapesVector.add(containers[i]);
        }
        if(this.shapesVector.size()>0) {
            this.goButton.setEnabled(true);
            //showMessage("  Selected shapes are accepted !", Color.BLUE);
        }
        else {
            showMessage("Select shapes before this command !", Color.RED);
            this.shapesVector.clear();
        }
    }
/*
    public void selected(SelectionEvent event){
        //Point2D point=event.getClickedPoint();
        ShapeContainer[] containers=event.getSelectedContainers();
        for(int i=0;i<containers.length;i++){
            this.shapesVector.add(containers[i]); 
            containers[i].setSelected(true);
        }
        if(this.shapesVector.size()>0) {
            showMessage("  Selected shape is accepted !", Color.BLUE);
            this.goButton.setEnabled(true);
        }
    }
*/
   public void addConnectionListener(){
        ConnectionLS connectionLS=ObjectTable.getConnectionLS();
        connectionLS.activateListener(true);
        connectionLS.addConnectionListener(this);
        ObjectTable.getSelectionLS().end();
        this.twoPointsVector.clear();
        this.showMessage("Click at the first point", Color.BLUE);
    }
   
    public void removeConnectionListener(){
        ConnectionLS connectionLS=ObjectTable.getConnectionLS();
        connectionLS.activateListener(false);
        connectionLS.removeConnectionListener(this);
        this.twoPointsVector.clear();
        ObjectTable.getSelectionLS().start();
    }
    
    public void connected(ConnectionEvent event){
        CurvePT curvePT=event.getCurvePT();
        this.twoPointsVector.add(curvePT.getP());
        int size=this.twoPointsVector.size();
        if(debug>0) System.out.println("** Debug Translate.connected curvePT="+Util.Pt(curvePT.getP()));
        if(size==1) {
            DrawShapeUtil.clearTempShape("Translate");
            this.translateVec=new Vector2D(0,0);
            this.showMessage("Click at the second point", Color.BLUE);
            Point2D startPoint=(Point2D)this.twoPointsVector.get(0);
            this.drawMark(startPoint, "p1");
        }
        if(size==2) {
            Point2D startPoint=(Point2D)this.twoPointsVector.get(0);
            Point2D endPoint=(Point2D)this.twoPointsVector.get(1);
            this.drawMark(endPoint, "p2");
            this.translateVec=Vector2D.sub(endPoint, startPoint);
            this.setValuesToTranslateSpinners();
            this.showMessage("Translation defined", Color.BLUE);
            this.twoPointsVector.clear();
        }
    }

    public void drawMark(Point2D point, String message){
        ObjectTable.getDrawPanel().repaint();
        DrawShapeUtil.drawTempShape("Translate", point,
                DrawParameters.Mark_SmallSize, message, Color.RED);
    }
    
    protected void showMessage(String message, Color color){
        this.messageLabel.setForeground(color);
        this.messageLabel.setFont(DrawParameters.Font12Bold);
        this.messageLabel.setText(message);

    }
    
    public void setValuesToTranslateSpinners(){
        double vecX=this.translateVec.getX();
        double vecY=this.translateVec.getY();
        double mm=DrawParameters.InchToMM/DrawParameters.InchToPixels;
        double unit=1.0d;
        if(this.mmButton.isSelected()) unit=mm;
        vecX=vecX*unit;
        vecY=vecY*unit;
        this.translateSpinners[0].setValue(vecX);
        this.translateSpinners[1].setValue(vecY);
    }
    
    public ShapeContainer[] getSelectedContainers(){
        int size=this.shapesVector.size();
        ShapeContainer[] containers=new ShapeContainer[size];
        for(int i=0;i<size;i++){
            containers[i]=(ShapeContainer)this.shapesVector.get(i);
        }
        return containers;
    }

    public JSpinner[] getTranslateSpinners(){
        return this.translateSpinners;
    }
    
    public SpinnerNumberModel[] getTranslateSpinnerModels(){
        return this.translateSpinnerModels;
    }

    public JRadioButton getCopyButton(){
        return this.copyButton;
    } 
    
    public Vector getShapeVector(){
        return this.shapesVector;
    } 
    
} //end of DialogOfConnectCurves

class TranslateAction extends AbstractAction implements WindowListener {
    Translate dialog=null;
    int debug=0;
    
    public TranslateAction(Translate dialog){
        this.dialog=dialog;
    }
    
    public void actionPerformed(ActionEvent e) {

        String commandName=e.getActionCommand();
        String componentClassName=""; 
        componentClassName=e.getSource().getClass().getSimpleName();
        String componentName=((Component)e.getSource()).getName();
        if(debug>0) System.out.println("- TranslateAction.actionPerformed  " +
                "commandName="+commandName+
                ", source component name="+componentName+
                ", source class simple name="+componentClassName);
        
        if(commandName.equals("click")){
            JCheckBox checkBox=this.dialog.checkBox;
            DrawShapeUtil.clearTempShape("Translate");
            ObjectTable.getDrawPanel().repaint();
            if(checkBox.isSelected()) {
                this.dialog.addConnectionListener();
            } else {
                this.dialog.removeConnectionListener();
                ObjectTable.getSelectionLS().start();
            }
        }
        
        if(commandName.equals("pixel")||commandName.equals("mm")){
            this.dialog.setValuesToTranslateSpinners();
        }
        
        if(commandName.equals("Go")){
            JRadioButton copyButton=this.dialog.getCopyButton();
            boolean copy=copyButton.isSelected();
            Vector shapesVector=this.dialog.getShapeVector();
            int size=shapesVector.size();
            if(size==0) return;
            ShapeContainer[] containers=new ShapeContainer[size];
            for(int i=0;i<size;i++) containers[i]=(ShapeContainer)shapesVector.get(i);
            ShapeContainer[] newContainers=new ShapeContainer[size];
            ContainerManager containerManager=ObjectTable.getContainerManager("");
            Vector2D translateVec=this.dialog.translateVec;
            if(Vector2D.length(translateVec)==0d){
                this.dialog.showMessage("** Error: specify non-zero (x,y) !!", Color.RED);
                return;
            }
          //--------------------------------------------//
            containerManager.undoSetupStart(containers);
          //--------------------------------------------//
            for(int i=0;i<size;i++) {
                newContainers[i]=this.translateContainer(containers[i], translateVec, copy);
                containers[i].setSelected(false);
                if(copy) {
                    newContainers[i].setSelected(true);
                    newContainers[i].setNewShapeId(containerManager, true);
                    containerManager.addContainer(newContainers[i]);
                } else {
                    newContainers[i].setChangeCode(UndoConstants.CONTAINER);
                }
            }
          //-------------------------------------------------------//  
            containerManager.undoSetupEnd();
          //-------------------------------------------------------//
            shapesVector.clear();
            for(int i=0;i<newContainers.length;i++) shapesVector.add(newContainers[i]);
            ObjectTable.getDrawPanel().repaint("translate");
        }
        if(commandName.equals("Cancel")){
            closeDialog();
        }
    }//End of actionPerformed
    
    private ShapeContainer translateContainer(ShapeContainer container, 
            Vector2D translateVec, boolean copy){
        ShapeContainer newContainer=container;
        if(copy) newContainer=(ShapeContainer)container.clone();
        ShapeElement element=newContainer.getElement();
        Rectangle2D oldBox=element.getBoundingBox();
        Rectangle2D newBox=new Rectangle2D.Double(oldBox.getX()+translateVec.getX(), 
                oldBox.getY()+translateVec.getY(), oldBox.getWidth(), oldBox.getHeight());
        element.moveResize(oldBox, newBox, true);
        return newContainer;
    }

    private void closeDialog(){
        this.dialog.setVisible(false);
        DrawPanel drawPanel=ObjectTable.getDrawPanel("");
      //-----------------------------------------// 
        DrawShapeUtil.clearTempShape("Translate");
        drawPanel.repaint();
      //-----------------------------------------// 
        SelectionLS selectionLS=ObjectTable.getSelectionLS();
        selectionLS.removeSelectionListener();
        this.dialog.removeConnectionListener();
        ObjectTable.getSelectionLS().start();
        return;
    }
    
    public void windowActivated(WindowEvent e) {}
    public void windowClosed(WindowEvent e) {}
    public void windowClosing(WindowEvent e) {
        this.closeDialog();
    }
    public void windowDeactivated(WindowEvent e) {}
    public void windowDeiconified(WindowEvent e) {}
    public void windowIconified(WindowEvent e) {}
    public void windowOpened(WindowEvent e) {}
} // end of class

class TranslateSpinnerListener implements ChangeListener{
    Translate dialog=null;
    int debug=0;
    TranslateSpinnerListener(Translate dialog){
        this.dialog=dialog;
    }
    public void stateChanged(ChangeEvent e){
        JSpinner spinner=(JSpinner)e.getSource();
        if(spinner==this.dialog.translateSpinners[0]||
               spinner==this.dialog.translateSpinners[1]){
            SpinnerNumberModel[] translateSpinnerModels
                =this.dialog.getTranslateSpinnerModels();
            double pixel=DrawParameters.InchToPixels/DrawParameters.InchToMM;
            double mm=DrawParameters.InchToMM/DrawParameters.InchToPixels;
            double unit=1.0d;
            if(this.dialog.mmButton.isSelected()) unit=pixel;
            double x=unit*translateSpinnerModels[0].getNumber().doubleValue();
            double y=unit*translateSpinnerModels[1].getNumber().doubleValue();
            this.dialog.translateVec=new Vector2D(x,y);
            double len=Vector2D.length(this.dialog.translateVec);
            if(len==0d) this.dialog.showMessage("** Error: specify non-zero (x,y) !!", Color.RED);
            else this.dialog.showMessage("(x,y) specified !", Color.BLUE);
        }
    }
}