/*
!=======================================================================
!
!  PROGRAM  PHASE-Viewer  (PHASE-Viewer 2014.01 ver.3.3.0)
!
!  Created on 2006/08/31, 13:40
!  AUTHOR(S): KOGA, Junichiro
!  File : RotateKeyListener.java
!  
!  Contact address :  Phase System Consortium
!                     E-mail: phase_system@nims.go.jp URL https://azuma.nims.go.jp
!
!
!   Since 2002, this program set had been intensively developed as a part of the following 
!  national projects supported by the Ministry of Education, Culture, Sports, Science and
!  Technology (MEXT) of Japan; "Frontier Simulation Software for Industrial Science
!  (FSIS)" from 2002 to 2005, "Revolutionary Simulation Software (RSS21)" from 2006 to
!  2008. "Research and Development of Innovative Simulation Software (RISS)" from 2008
!  to 2013. These projects is lead by the Center for Research on Innovative Simulation 
!  Software (CISS), the Institute of Industrial Science (IIS), the University of Tokyo.
!   Since 2013, this program set has been further developed centering on PHASE System
!  Consortium. 
!   The activity of development of this program set has been supervised by Takahisa Ohno.
!
!=======================================================================
 */

package ciss.phase_viewer.acviewer.keylistener;

import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;

import javax.media.j3d.Transform3D;
import javax.media.j3d.TransformGroup;
import javax.vecmath.Matrix4d;
import javax.vecmath.Vector3d;

import org.apache.log4j.Logger;

import ciss.phase_viewer.settings.GlobalProperties;
import ciss.phase_viewer.settings.PropertiesListener;
import ciss.phase_viewer.settings.PropertiesManager;

/**
 * 「回転」を施す
 * 
 * @author
 */
public class RotateKeyListener implements KeyListener, PropertiesListener {
    private Logger logger = Logger.getLogger(RotateKeyListener.class.getName());

    private double factor = Math.PI / 180d;
    private double rotFactorX = 2.5 * factor;
    private double rotFactorY = 2.5 * factor;

    private double ninetyDegrees = Math.PI / 2d;

    private TransformGroup[] transformGroups;

    /**
     * このクラスによって回転を施したい全TransformGroupの配列を渡す.
     * 
     * @param transformGroups
     *            (同一の)回転を施したいTransformGroup
     */
    public RotateKeyListener(TransformGroup[] transformGroups) {
        this.transformGroups = transformGroups;
        PropertiesManager.getGlobalProperties(PropertiesManager.PROPERTIES_ACV)
                .addPropertiesListener(this);
        init();
    }

    private void init() {
        GlobalProperties props = PropertiesManager
                .getGlobalProperties(PropertiesManager.PROPERTIES_ACV);
        try {
            rotFactorX = Double.parseDouble(props
                    .getProperty("keylistener_rot")) * factor;
            rotFactorY = Double.parseDouble(props
                    .getProperty("keylistener_rot")) * factor;
        } catch (Exception exc) {
        }
    }

    private double rotx;
    private double roty;

    //
    // Transform3D transformX = new Transform3D();
    // Transform3D transformY = new Transform3D();
    // Transform3D currTrans = new Transform3D();
    /**
     * 登録されているTransformGroupをまわす. 第一引数でx周り, 第二引数でy周りにどのように回転するかを指定.
     * 
     * @param xincre
     *            x周りの回転量; 正負も関係ある.
     * @param yincre
     *            y周りの回転量; 正負も関係ある.
     */
    private void rotate(int xincre, int yincre) {
        double x_angle = yincre * roty;
        double y_angle = xincre * rotx;
        Transform3D transformX = new Transform3D();
        Transform3D transformY = new Transform3D();
        transformX.rotX(x_angle);
        transformY.rotY(y_angle);
        for (int i = 0; i < transformGroups.length; i++) {
            Transform3D currTrans = new Transform3D();
            TransformGroup transformGroup = transformGroups[i];
            transformGroup.getTransform(currTrans);
            Matrix4d mat = new Matrix4d();
            // Remember old matrix
            currTrans.get(mat);

            // Translate to origin
            currTrans.setTranslation(new Vector3d(0.0, 0.0, 0.0));
            currTrans.mul(transformX, currTrans);
            currTrans.mul(transformY, currTrans);

            // Set old translation back
            Vector3d translation = new Vector3d(mat.m03, mat.m13, mat.m23);
            currTrans.setTranslation(translation);
            transformGroup.setTransform(currTrans);
        }

    }

    public void keyTyped(java.awt.event.KeyEvent e) {
    }

    public void keyReleased(java.awt.event.KeyEvent e) {
        // if ( e.getKeyCode() == KeyEvent.VK_UP ) {
        // rotate(0,-1);
        // } else if ( e.getKeyCode() == KeyEvent.VK_DOWN ) {
        // rotate(0,1);
        // } else if ( e.getKeyCode() == KeyEvent.VK_LEFT ) {
        // rotate(-1,0);
        // } else if ( e.getKeyCode() == KeyEvent.VK_RIGHT ) {
        // rotate(1,0);
        // }
    }

    public void keyPressed(java.awt.event.KeyEvent e) {
        if (e.isShiftDown())
            return;
        if (e.isAltDown())
            return;
        if (e.isControlDown()) {
            rotx = ninetyDegrees;
            roty = ninetyDegrees;
        }
        if (e.getKeyCode() == KeyEvent.VK_UP || e.getKeyCode() == KeyEvent.VK_K) {
            rotate(0, -1);
        } else if (e.getKeyCode() == KeyEvent.VK_DOWN
                || e.getKeyCode() == KeyEvent.VK_J) {
            rotate(0, 1);
        } else if (e.getKeyCode() == KeyEvent.VK_LEFT
                || e.getKeyCode() == KeyEvent.VK_H) {
            rotate(-1, 0);
        } else if (e.getKeyCode() == KeyEvent.VK_RIGHT
                || e.getKeyCode() == KeyEvent.VK_L) {
            rotate(1, 0);
        }
        rotx = rotFactorX;
        roty = rotFactorY;
    }

    public void propertiesStored(GlobalProperties properties) {
        init();
    }

}
