/*
!=======================================================================
!
!  PROGRAM  PHASE-Viewer  (PHASE-Viewer 2014.01 ver.3.3.0)
!
!  Created on 2007/04/13 11:14:12
!  AUTHOR(S): KOGA, Junichiro
!  File : AtomCoordsTrans.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.plugins.viewer.view;

import javax.media.j3d.Node;
import javax.swing.BoxLayout;
import javax.swing.JPanel;
import javax.swing.JSpinner;
import javax.swing.SpinnerNumberModel;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import javax.vecmath.Vector3d;

import org.apache.log4j.Logger;

import ciss.phase_viewer.acviewer.ChaseTransformGroup;
import ciss.phase_viewer.acviewer.scenegraphelements.Contour;
import ciss.phase_viewer.acviewer.scenegraphelements.Isosurface;
import ciss.phase_viewer.acviewer.scenegraphelements.TGAtom;
import ciss.phase_viewer.atomcoord.VolumetricData;
import ciss.phase_viewer.primitiveguis.ValueSlider;
import ciss.phase_viewer.primitiveguis.ValueSliderListener;

public class AtomCoordsTrans extends JPanel implements ValueSliderListener,
        ChangeListener {
    private Logger logger = Logger.getLogger(AtomCoordsTrans.class);
    private TGAtom tgatom;
    private VolumetricData[] vdata;

    private JSpinner spinnera;
    private JSpinner spinnerb;
    private JSpinner spinnerc;

    private SpinnerNumberModel modela;
    private SpinnerNumberModel modelb;
    private SpinnerNumberModel modelc;

    /** Creates a new instance of AtomCoordsTranslationPanel */
    public AtomCoordsTrans(TGAtom tgatom) {
        this.tgatom = tgatom;
        vdata = this.tgatom.getParentFrame().getAssociatedVolumetricData();
        init();
    }

    private ValueSlider slider_a;
    private ValueSlider slider_b;
    private ValueSlider slider_c;
    private float prev_a = 0f;
    private float prev_b = 0f;
    private float prev_c = 0f;

    private void init() {

        setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));

        float increa = 0.01f;
        float increb = 0.01f;
        float increc = 0.01f;

        if (vdata != null) {
            int[] div = vdata[0].getNumDiv();
            increa = 1f / ((float) (div[0] - 1));
            increb = 1f / ((float) (div[1] - 1));
            increc = 1f / ((float) (div[2] - 1));
            logger.debug("increment: " + increa + ", " + increb + ", " + increc);
        }

        double[][] cellvec = tgatom.getConfigData().getCell();
        if (cellvec == null) {
            logger.error("invalid cell data");
            return;
        }

        double d0 = 0;
        double d1 = 0;
        double d2 = 0;
        Vector3d vec = tgatom.getOffset();
        if (vec != null) {
            d0 = vec.x;
            d1 = vec.y;
            d2 = vec.z;
        }

        modela = new SpinnerNumberModel(0, -0.5, 0.5, (double) increa);
        modelb = new SpinnerNumberModel(0, -0.5, 0.5, (double) increa);
        modelc = new SpinnerNumberModel(0, -0.5, 0.5, (double) increa);
        spinnera = new JSpinner(modela);
        spinnerb = new JSpinner(modelb);
        spinnerc = new JSpinner(modelc);
        spinnera.setValue(new Double(d0));
        spinnerb.setValue(new Double(d1));
        spinnerc.setValue(new Double(d2));

        spinnera.addChangeListener(this);
        spinnerb.addChangeListener(this);
        spinnerc.addChangeListener(this);

        logger.debug("init val : " + d0 + ", " + d1 + ", " + d2);

        slider_a = new ValueSlider(-0.5f, 0.5f, increa);
        slider_a.setOrientation(ValueSlider.VERTICAL);
        slider_a.setTitleForBorder("a-axis");
        slider_b = new ValueSlider(-0.5f, 0.5f, increb);
        slider_b.setOrientation(ValueSlider.VERTICAL);
        slider_b.setTitleForBorder("b-axis");
        slider_c = new ValueSlider(-0.5f, 0.5f, increc);
        slider_c.setOrientation(ValueSlider.VERTICAL);
        slider_c.setTitleForBorder("c-axis");

        slider_a.setValue((float) d0);
        slider_b.setValue((float) d1);
        slider_c.setValue((float) d2);

        slider_a.addValueSliderListener(this);
        slider_b.addValueSliderListener(this);
        slider_c.addValueSliderListener(this);

        JPanel pa = new JPanel();
        pa.add(slider_a);
        // pa.add(spinnera);

        JPanel pb = new JPanel();
        pb.add(slider_b);
        // pb.add(spinnerb);

        JPanel pc = new JPanel();
        pc.add(slider_c);
        // pc.add(spinnerc);

        add(pa);
        add(pb);
        add(pc);

        prev_a = slider_a.getValue();
        prev_b = slider_b.getValue();
        prev_c = slider_c.getValue();
    }

    public void dispose() {
        slider_a.removeValueSliderListener(this);
        slider_b.removeValueSliderListener(this);
        slider_c.removeValueSliderListener(this);
    }

    public void valueSliderValueChanged() {
        double a = (double) (slider_a.getValue() - prev_a);
        double b = (double) (slider_b.getValue() - prev_b);
        double c = (double) (slider_c.getValue() - prev_c);
        if (a == 0 && b == 0 && c == 0)
            return;

        Node[] isosurfs = ((ChaseTransformGroup) tgatom)
                .getChildren(Isosurface.class);
        if (isosurfs != null) {
            logger.debug("found isosurface");
            for (int i = 0; i < isosurfs.length; i++) {
                ((Isosurface) isosurfs[i]).forceCreation(true);
            }
        }

        Node[] conts = tgatom.getChildren(Contour.class);
        if (conts != null) {
            for (int i = 0; i < conts.length; i++) {
                ((Contour) conts[i]).forceCreation(true);
            }
        }

        tgatom.setAtomOffset(new Vector3d(a, b, c));
        tgatom.setOffset(new Vector3d(slider_a.getValue(), slider_b.getValue(),
                slider_c.getValue()));
        tgatom.getConfigData().update();
        prev_a = (float) slider_a.getValue();
        prev_b = (float) slider_b.getValue();
        prev_c = (float) slider_c.getValue();

        if (vdata != null) {
            for (int i = 0; i < vdata.length; i++) {
                vdata[i].setShift((double) slider_a.getValue(),
                        (double) slider_b.getValue(),
                        (double) slider_c.getValue());
                // vdata[i].setDiffShift(a, b, c);
            }
        }

    }

    public void stateChanged(ChangeEvent e) {
        double anow = 0;
        double bnow = 0;
        double cnow = 0;

        try {
            anow = Double.parseDouble(spinnera.getValue().toString()) - prev_a;
            bnow = Double.parseDouble(spinnerb.getValue().toString()) - prev_b;
            cnow = Double.parseDouble(spinnerc.getValue().toString()) - prev_c;
        } catch (NumberFormatException e1) {
            logger.error("enter value between -0.5 to 0.5");
            return;
        }

        double a = anow - prev_a;
        double b = bnow - prev_b;
        double c = cnow - prev_c;

        if (a == 0 && b == 0 && c == 0)
            return;

        Node[] isosurfs = ((ChaseTransformGroup) tgatom)
                .getChildren(Isosurface.class);
        if (isosurfs != null) {
            logger.debug("found isosurface");
            for (int i = 0; i < isosurfs.length; i++) {
                ((Isosurface) isosurfs[i]).forceCreation(true);
            }
        }

        Node[] conts = tgatom.getChildren(Contour.class);
        if (conts != null) {
            for (int i = 0; i < conts.length; i++) {
                ((Contour) conts[i]).forceCreation(true);
            }
        }

        tgatom.setAtomOffset(new Vector3d(a, b, c));
        tgatom.setOffset(new Vector3d(anow, bnow, cnow));
        tgatom.getConfigData().update();
        prev_a = (float) anow;
        prev_b = (float) bnow;
        prev_c = (float) cnow;

        if (vdata != null) {
            for (int i = 0; i < vdata.length; i++) {
                vdata[i].setShift(anow, bnow, cnow);
            }
        }
    }

}
