import java.io.IOException;
import java.util.*;
import javax.swing.*;
import javax.media.j3d.Node;
import vfs.Vfs;


// メモ:
// ListModelと3Dのモデルがまぎらわしいので、後者はObj3Dと呼ぶことにする。
// JListとArrayListがまぎらわしいので、後者はxxx arrayと呼ぶことにする。

public class Viewer2 extends javax.swing.JFrame {
    Vfs mVfs;
    ArrayList<Category> mCatArray;
    int mCategoryIndex;
    Panel3D mPanel3D;

    static final String DATA_DIR = "unpacked";

    /** Creates new form Viewer2 */
    public Viewer2() throws IOException {
	mVfs = Vfs.create(Vfs.SCHEME_FILE, DATA_DIR);

	// オブジェクトのリストを構築
	CategoryListBuilder clb = new CategoryListBuilder(DATA_DIR);
	mCatArray = clb.buildList();

	// GUI部品を設定
	initComponents();
	mPanel3D = new Panel3D();
	mPanel3D.setVisible(true);
	jPanel1.setLayout(new java.awt.BorderLayout());
	jPanel1.add(mPanel3D);
	jPanel1.setVisible(true);
	catList.setModel(new DefaultListModel());
	modelList.setModel(new DefaultListModel());

	// GUI部品にオブジェクトのリストを登録
	DefaultListModel listModel = (DefaultListModel)catList.getModel();
	for(Category c: mCatArray)
	    listModel.addElement(c);
    }

    void reloadModelList(int catIndex) {
	Category c = mCatArray.get(catIndex);
	DefaultListModel listModel = (DefaultListModel)modelList.getModel();
	listModel.clear();
	for(Obj3D obj: c.mObjArray)
	    listModel.addElement(obj);
    }

    void unloadObject() {
	mPanel3D.clearSceneGraph();
    }

    void loadObject(int catIndex, int objIndex) {
	Category cat = null;
	Obj3D obj = null;
	Node node = null;
	try {
	    cat = mCatArray.get(catIndex);
	    obj = cat.getObject(objIndex);
	    node = obj.getObject(mVfs);
	    mPanel3D.setSceneGraph(node);
	} catch(Exception e) {
	    jTextArea1.append(e.toString() + "\n");
	    throw new RuntimeException(e); // debug
	}
    }


    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        jMenuBar1 = new javax.swing.JMenuBar();
        jMenu1 = new javax.swing.JMenu();
        jMenu2 = new javax.swing.JMenu();
        jScrollPane1 = new javax.swing.JScrollPane();
        catList = new javax.swing.JList();
        jScrollPane2 = new javax.swing.JScrollPane();
        modelList = new javax.swing.JList();
        jPanel1 = new javax.swing.JPanel();
        jLabel1 = new javax.swing.JLabel();
        jLabel2 = new javax.swing.JLabel();
        jScrollPane3 = new javax.swing.JScrollPane();
        jTextArea1 = new javax.swing.JTextArea();
        jMenuBar2 = new javax.swing.JMenuBar();
        jMenu3 = new javax.swing.JMenu();
        jMenuItem1 = new javax.swing.JMenuItem();
        jMenu4 = new javax.swing.JMenu();
        blackBackgroundBtn = new javax.swing.JMenuItem();
        grayBackgroundBtn = new javax.swing.JMenuItem();
        whiteBackgroundBtn = new javax.swing.JMenuItem();
        blueBackgroundBtn = new javax.swing.JMenuItem();
        clearLogBtn = new javax.swing.JMenuItem();
        resetCameraPosBtn = new javax.swing.JMenuItem();

        jMenu1.setText("File");
        jMenuBar1.add(jMenu1);

        jMenu2.setText("Edit");
        jMenuBar1.add(jMenu2);

        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
        setTitle("ai sp@ce model viewer");

        catList.setFont(catList.getFont().deriveFont(catList.getFont().getStyle() & ~java.awt.Font.BOLD));
        catList.setSelectionMode(javax.swing.ListSelectionModel.SINGLE_SELECTION);
        catList.addListSelectionListener(new javax.swing.event.ListSelectionListener() {
            public void valueChanged(javax.swing.event.ListSelectionEvent evt) {
                catListValueChanged(evt);
            }
        });
        jScrollPane1.setViewportView(catList);

        modelList.setFont(modelList.getFont().deriveFont(modelList.getFont().getStyle() & ~java.awt.Font.BOLD));
        modelList.setSelectionMode(javax.swing.ListSelectionModel.SINGLE_SELECTION);
        modelList.addListSelectionListener(new javax.swing.event.ListSelectionListener() {
            public void valueChanged(javax.swing.event.ListSelectionEvent evt) {
                modelListValueChanged(evt);
            }
        });
        jScrollPane2.setViewportView(modelList);

        jPanel1.setBorder(javax.swing.BorderFactory.createLineBorder(new java.awt.Color(0, 0, 0)));
        jPanel1.setPreferredSize(new java.awt.Dimension(640, 480));

        javax.swing.GroupLayout jPanel1Layout = new javax.swing.GroupLayout(jPanel1);
        jPanel1.setLayout(jPanel1Layout);
        jPanel1Layout.setHorizontalGroup(
            jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGap(0, 809, Short.MAX_VALUE)
        );
        jPanel1Layout.setVerticalGroup(
            jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGap(0, 657, Short.MAX_VALUE)
        );

        jLabel1.setText("カテゴリ");

        jLabel2.setText("表示モデル");

        jTextArea1.setColumns(20);
        jTextArea1.setRows(5);
        jScrollPane3.setViewportView(jTextArea1);

        jMenu3.setText("File");

        jMenuItem1.setAccelerator(javax.swing.KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_Q, java.awt.event.InputEvent.CTRL_MASK));
        jMenuItem1.setText("Quit");
        jMenuItem1.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jMenuItem1ActionPerformed(evt);
            }
        });
        jMenu3.add(jMenuItem1);

        jMenuBar2.add(jMenu3);

        jMenu4.setText("Edit");

        blackBackgroundBtn.setText("背景を黒にする");
        blackBackgroundBtn.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                blackBackgroundBtnActionPerformed(evt);
            }
        });
        jMenu4.add(blackBackgroundBtn);

        grayBackgroundBtn.setText("背景を灰にする");
        grayBackgroundBtn.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                grayBackgroundBtnActionPerformed(evt);
            }
        });
        jMenu4.add(grayBackgroundBtn);

        whiteBackgroundBtn.setText("背景を白にする");
        whiteBackgroundBtn.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                whiteBackgroundBtnActionPerformed(evt);
            }
        });
        jMenu4.add(whiteBackgroundBtn);

        blueBackgroundBtn.setText("背景を青にする");
        blueBackgroundBtn.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                blueBackgroundBtnActionPerformed(evt);
            }
        });
        jMenu4.add(blueBackgroundBtn);

        clearLogBtn.setText("ログをクリア");
        clearLogBtn.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                clearLogBtnActionPerformed(evt);
            }
        });
        jMenu4.add(clearLogBtn);

        resetCameraPosBtn.setText("カメラ位置をリセット");
        resetCameraPosBtn.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                resetCameraPosBtnActionPerformed(evt);
            }
        });
        jMenu4.add(resetCameraPosBtn);

        jMenuBar2.add(jMenu4);

        setJMenuBar(jMenuBar2);

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
        getContentPane().setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addContainerGap()
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(jScrollPane3, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, 1024, Short.MAX_VALUE)
                    .addGroup(layout.createSequentialGroup()
                        .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                            .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
                                .addComponent(jLabel2)
                                .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
                                    .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING, false)
                                        .addComponent(jScrollPane1, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.PREFERRED_SIZE, 195, javax.swing.GroupLayout.PREFERRED_SIZE)
                                        .addComponent(jLabel1, javax.swing.GroupLayout.Alignment.LEADING))
                                    .addGap(18, 18, 18)))
                            .addComponent(jScrollPane2, javax.swing.GroupLayout.PREFERRED_SIZE, 195, javax.swing.GroupLayout.PREFERRED_SIZE))
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(jPanel1, javax.swing.GroupLayout.DEFAULT_SIZE, 811, Short.MAX_VALUE)))
                .addContainerGap())
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addContainerGap()
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addGroup(layout.createSequentialGroup()
                        .addComponent(jLabel1)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 206, javax.swing.GroupLayout.PREFERRED_SIZE)
                        .addGap(18, 18, 18)
                        .addComponent(jLabel2)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(jScrollPane2, javax.swing.GroupLayout.DEFAULT_SIZE, 391, Short.MAX_VALUE))
                    .addComponent(jPanel1, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, 659, Short.MAX_VALUE))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(jScrollPane3, javax.swing.GroupLayout.PREFERRED_SIZE, 64, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addContainerGap())
        );

        pack();
    }// </editor-fold>//GEN-END:initComponents

    /**
     * カテゴリリストのエントリが選択された時の処理
     */
    private void catListValueChanged(javax.swing.event.ListSelectionEvent evt) {//GEN-FIRST:event_catListValueChanged
	mCategoryIndex = catList.getSelectedIndex();
	if(mCategoryIndex < 0)
	    return;
	reloadModelList(mCategoryIndex);
	unloadObject();
    }//GEN-LAST:event_catListValueChanged

    /**
     * モデルリストのエントリが選択された時の処理
     */
    private void modelListValueChanged(javax.swing.event.ListSelectionEvent evt) {//GEN-FIRST:event_modelListValueChanged
	int modelIndex = modelList.getSelectedIndex();
	if(modelIndex < 0)
	    return;
	unloadObject();
	loadObject(mCategoryIndex, modelIndex);
    }//GEN-LAST:event_modelListValueChanged

    private void jMenuItem1ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jMenuItem1ActionPerformed
	System.exit(0);
    }//GEN-LAST:event_jMenuItem1ActionPerformed

    private void clearLogBtnActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_clearLogBtnActionPerformed
	jTextArea1.removeAll();
}//GEN-LAST:event_clearLogBtnActionPerformed

    private void resetCameraPosBtnActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_resetCameraPosBtnActionPerformed
	mPanel3D.resetCameraPos();
}//GEN-LAST:event_resetCameraPosBtnActionPerformed

    private void grayBackgroundBtnActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_grayBackgroundBtnActionPerformed
	mPanel3D.setBackgroundColor(0.5f, 0.5f, 0.5f);
    }//GEN-LAST:event_grayBackgroundBtnActionPerformed

    private void blackBackgroundBtnActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_blackBackgroundBtnActionPerformed
	mPanel3D.setBackgroundColor(0f, 0f, 0f);
    }//GEN-LAST:event_blackBackgroundBtnActionPerformed

    private void whiteBackgroundBtnActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_whiteBackgroundBtnActionPerformed
	mPanel3D.setBackgroundColor(1f, 1f, 1f);
    }//GEN-LAST:event_whiteBackgroundBtnActionPerformed

    private void blueBackgroundBtnActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_blueBackgroundBtnActionPerformed
	mPanel3D.setBackgroundColor(0f, 0f, 1f);
    }//GEN-LAST:event_blueBackgroundBtnActionPerformed

    /**
    * @param args the command line arguments
    */
    public static void main(String args[]) {
        java.awt.EventQueue.invokeLater(new Runnable() {
            public void run() {
		try {
		    new Viewer2().setVisible(true);
		} catch(Exception ex) {
		    ex.printStackTrace();
		    throw new RuntimeException(ex);
		}
            }
        });
    }

    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JMenuItem blackBackgroundBtn;
    private javax.swing.JMenuItem blueBackgroundBtn;
    private javax.swing.JList catList;
    private javax.swing.JMenuItem clearLogBtn;
    private javax.swing.JMenuItem grayBackgroundBtn;
    private javax.swing.JLabel jLabel1;
    private javax.swing.JLabel jLabel2;
    private javax.swing.JMenu jMenu1;
    private javax.swing.JMenu jMenu2;
    private javax.swing.JMenu jMenu3;
    private javax.swing.JMenu jMenu4;
    private javax.swing.JMenuBar jMenuBar1;
    private javax.swing.JMenuBar jMenuBar2;
    private javax.swing.JMenuItem jMenuItem1;
    private javax.swing.JPanel jPanel1;
    private javax.swing.JScrollPane jScrollPane1;
    private javax.swing.JScrollPane jScrollPane2;
    private javax.swing.JScrollPane jScrollPane3;
    private javax.swing.JTextArea jTextArea1;
    private javax.swing.JList modelList;
    private javax.swing.JMenuItem resetCameraPosBtn;
    private javax.swing.JMenuItem whiteBackgroundBtn;
    // End of variables declaration//GEN-END:variables

}
