/*
!=======================================================================
!
!  PROGRAM  PHASE-Viewer  (PHASE-Viewer 2014.01 ver.3.3.0)
!
!  Created on 2006/07/07, 17:47
!  AUTHOR(S): KOGA, Junichiro
!  File : ColorMapPanel.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.colormap;

import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Vector;

import javax.media.j3d.BranchGroup;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JComboBox;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.border.TitledBorder;
import javax.vecmath.Point3f;

import org.apache.log4j.Logger;

import ciss.phase_viewer.acviewer.J3DPanel;
import ciss.phase_viewer.settings.GlobalProperties;
import ciss.phase_viewer.settings.PropertiesManager;

/**
 * カラーマップなどの諸々の操作をひとくくりにしたGUI
 * 
 * @author
 */
public class ColorMapPanel extends JPanel {
    private Logger logger = Logger.getLogger(ColorMapPanel.class.getName());
    private J3DPanel parent;

    private JComboBox colorBars;
    private JButton update;
    private JButton add;
    private JButton remove;

    /**
     * Creates a new instance of ColorMapPanel
     */
    public ColorMapPanel(J3DPanel parent) {
        this.parent = parent;
        init();
    }

    private Vector colorBarChangeListeners = new Vector();

    /**
     * カラーバーの変更の通知を受けるリスナーを登録.
     * 
     * @param list
     *            カラーバーのリスナー
     */
    public void addColorBarChangeListener(ColorMapChangeListener list) {
        colorBarChangeListeners.addElement(list);
    }

    private GlobalProperties gp = PropertiesManager
            .getGlobalProperties(PropertiesManager.PROPERTIES_ACV);
    private JComboBox colorMaps;
    private JCheckBox invert;
    private JTextField textBarTitle;
    private JTextField textBarPosx;
    private JTextField textBarPosy;
    private JTextField textBarPosz;

    private void init() {
        setLayout(new BoxLayout(this, BoxLayout.X_AXIS));
        ColorMap[] maps = BaseColorMap.getSupportedColorMaps();
        colorMaps = new JComboBox(maps);
        if (maps == null || maps.length == 0) {
            logger.error("corrupted colormap file!!!");
        }

        JPanel pcmaps = new JPanel();
        pcmaps.setLayout(new BoxLayout(pcmaps, BoxLayout.X_AXIS));
        pcmaps.setBorder(new TitledBorder("color map"));

        JPanel pcm = new JPanel();
        pcm.setLayout(new GridBagLayout());
        GridBagConstraints gc = new GridBagConstraints();
        gc.fill = GridBagConstraints.NONE;
        gc.anchor = GridBagConstraints.WEST;
        pcm.add(colorMaps, gc);
        pcmaps.add(pcm);
        invert = new JCheckBox("invert");
        gc.anchor = GridBagConstraints.EAST;
        pcm.add(invert, gc);
        pcmaps.add(pcm);

        colorBars = new JComboBox();
        BranchGroup rootBranch = parent.getRootBranch();
        Vector cbars = new Vector();
        for (int i = 0; i < rootBranch.numChildren(); i++) {
            if (rootBranch.getChild(i) instanceof ColorBar) {
                cbars.add(rootBranch.getChild(i));
            }
        }

        if (cbars.size() != 0) {
            for (int i = 0; i < cbars.size(); i++) {
                colorBars.addItem(cbars.get(i));
            }
        }

        update = new JButton("update");
        add = new JButton("add");
        remove = new JButton("remove");
        JPanel pcbars = new JPanel();
        pcbars.setLayout(new BoxLayout(pcbars, BoxLayout.X_AXIS));
        pcbars.setBorder(new TitledBorder("color bar"));
        JPanel pup = new JPanel();
        pup.add(update);
        JPanel padd = new JPanel();
        padd.add(add);
        JPanel prem = new JPanel();
        prem.add(remove);

        JPanel pcolorBars = new JPanel();
        pcolorBars.add(colorBars);
        pcbars.add(pcolorBars);
        JPanel pbtns = new JPanel();
        pbtns.setLayout(new BoxLayout(pbtns, BoxLayout.X_AXIS));
        pbtns.add(pup);
        pbtns.add(padd);
        pbtns.add(prem);
        pcbars.add(pbtns);
        //
        // JPanel pcbar = new JPanel();
        // pcbar.setLayout(new BoxLayout(pcbar,BoxLayout.X_AXIS));
        // // pcbar.setBorder(new TitledBorder("colorbar"));
        // JPanel pgen = new JPanel();
        // pgen.setLayout(new BorderLayout());

        JPanel pcbarattr = new JPanel();
        pcbarattr.setBorder(new TitledBorder("color bar attributes"));
        JPanel ptitle = new JPanel();
        ptitle.setBorder(new TitledBorder("title"));
        textBarTitle = new JTextField(10);
        ptitle.add(textBarTitle);
        //
        // JPanel pbar = new JPanel();
        // pbar.add(colorbar);
        // pbar.add(update);
        // pgen.add(pbar,BorderLayout.NORTH);
        // pgen.add(ptitle);

        JPanel pos = new JPanel();
        pos.setLayout(new BoxLayout(pos, BoxLayout.X_AXIS));
        pos.setBorder(new TitledBorder("position"));

        String[] pospos = null;
        try {
            pospos = gp.getProperty("colorbar_position").split(",");
        } catch (Exception exc) {
            exc.printStackTrace();
        }

        JPanel posx = new JPanel();
        posx.setBorder(new TitledBorder("x"));
        textBarPosx = new JTextField(5);
        posx.add(textBarPosx);

        JPanel posy = new JPanel();
        posy.setBorder(new TitledBorder("y"));
        textBarPosy = new JTextField(5);
        posy.add(textBarPosy);

        JPanel posz = new JPanel();
        posz.setBorder(new TitledBorder("z"));
        textBarPosz = new JTextField(5);
        posz.add(textBarPosz);

        if (pospos != null && pospos.length >= 3) {
            textBarPosx.setText(pospos[0]);
            textBarPosy.setText(pospos[1]);
            textBarPosz.setText(pospos[2]);
        }

        pos.add(posx);
        pos.add(posy);
        pos.add(posz);

        pcbarattr.add(ptitle);
        pcbarattr.add(pos);

        JPanel pcb = new JPanel();
        pcb.setLayout(new BoxLayout(pcb, BoxLayout.Y_AXIS));
        pcb.add(pcbars);
        pcb.add(pcbarattr);
        //
        // pcbar.add(pgen);
        // pcbar.add(pos);

        add(pcmaps);
        add(pcb);
        // add(pcbar);

        colorBars.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                updateGUI();
            }
        });

        add.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                drawColorBar();
            }
        });

        remove.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                removeColorBar();
            }
        });

        invert.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent ae) {
                updateAllColorBars();
                notifyColorBarListeners();
            }
        });

        colorMaps.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent ae) {
                updateAllColorBars();
                notifyColorBarListeners();
            }
        });

        update.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                updateColorBar();
                notifyColorBarListeners();
            }
        });
    }

    private void updateGUI() {
        if (colorBars.getItemCount() == 0)
            return;
        ColorBar cb = (ColorBar) colorBars.getSelectedItem();
        if (cb == null)
            return;
        Point3f cen = cb.getPos();
        textBarPosx.setText(String.valueOf(cen.x));
        textBarPosy.setText(String.valueOf(cen.y));
        textBarPosz.setText(String.valueOf(cen.z));
        String tit = cb.getTitle();
        textBarTitle.setText(tit);
    }

    private void notifyColorBarListeners() {
        ColorMap cmap = null;
        Object obj = colorMaps.getSelectedItem();
        if (obj != null) {
            cmap = (ColorMap) obj;
        }
        boolean b = invert.isSelected();
        logger.debug("invert here: " + b);
        for (int i = 0; i < colorBarChangeListeners.size(); i++) {
            ((ColorMapChangeListener) colorBarChangeListeners.get(i))
                    .colorMapChanged(new ColorMapChangeEvent(cmap, b));
        }
    }

    /**
     * 選択中のカラーマップを取得する.
     * 
     * @return 選択中のカラーマップ
     */
    public ColorMap getSelectedColorMap() {
        Object obj = colorMaps.getSelectedItem();
        if (obj == null) {
            return null;
        }
        return (ColorMap) obj;
    }

    /**
     * カラーマップが"反転状態"にあるか否かを返す.
     * 
     * @return trueの場合カラーマップは反転状態
     */
    public boolean isInvert() {
        return invert.isSelected();
    }

    public void setEnabled(boolean enabled) {
        super.setEnabled(enabled);
        colorMaps.setEnabled(enabled);
        invert.setEnabled(enabled);
    }

    private float minval = 0f;
    private float maxval = 0f;

    /**
     * カラーバーの最小値をセット.
     * 
     * @param minval
     *            カラーバーの最小値
     */
    public void setMinVal(float minval) {
        this.minval = minval;
    }

    /**
     * カラーバーの最大値をセット
     * 
     * @param maxval
     *            カラーバーの最大値
     */
    public void setMaxVal(float maxval) {
        this.maxval = maxval;
    }

    private void drawColorBar() {
        // removeColorBar();
        ColorMap map = (ColorMap) colorMaps.getSelectedItem();
        boolean b = invert.isSelected();
        ColorBar bar = new ColorBar(map, b, new Float(minval),
                new Float(maxval), parent);
        bar.setTitle(textBarTitle.getText());
        Point3f center = null;
        try {
            float x = Float.parseFloat(textBarPosx.getText());
            float y = Float.parseFloat(textBarPosy.getText());
            float z = Float.parseFloat(textBarPosz.getText());
            center = new Point3f(x, y, z);
        } catch (Exception exc) {
            exc.printStackTrace();
        }
        if (center != null)
            bar.setPos(center);
        bar.setInterpolationMode(parent.getAssociatedVolumetricData()[0]
                .getInterpolationScheme());
        bar.create();
        parent.getRootBranch().addChild(bar);
        colorBars.addItem(bar);
        logger.debug("colorbar added.");
    }

    private void updateAllColorBars() {
        for (int i = 0; i < colorBars.getItemCount(); i++) {
            ColorBar bar = (ColorBar) colorBars.getItemAt(i);
            ColorMap map = (ColorMap) colorMaps.getSelectedItem();
            boolean b = invert.isSelected();
            bar.recreate(map, b);
        }
    }

    private void updateColorBar() {
        if (colorBars.getItemCount() == 0) {
            drawColorBar();
            return;
        }
        ColorBar bar = (ColorBar) colorBars.getSelectedItem();
        if (bar != null) {
            ColorMap map = (ColorMap) colorMaps.getSelectedItem();
            boolean b = invert.isSelected();
            bar.setTitle(textBarTitle.getText());
            Point3f center = null;
            try {
                float x = Float.parseFloat(textBarPosx.getText());
                float y = Float.parseFloat(textBarPosy.getText());
                float z = Float.parseFloat(textBarPosz.getText());
                center = new Point3f(x, y, z);
            } catch (Exception exc) {
                exc.printStackTrace();
            }
            if (center != null)
                bar.setPos(center);

            bar.recreate(map, b, new Float(minval), new Float(maxval));
        }
    }

    private void removeColorBar() {
        if (colorBars.getItemCount() == 0)
            return;
        try {
            ColorBar bar = (ColorBar) colorBars.getSelectedItem();
            if (bar != null) {
                bar.detach();
                colorBars.removeItem(bar);
            }
        } catch (Exception exc) {
            exc.printStackTrace();
        }
    }

}
