/*
!=======================================================================
!
!  PROGRAM  PHASE-Viewer  (PHASE-Viewer 2014.01 ver.3.3.0)
!
!  Created on 2006/01/23, 14:02
!  AUTHOR(S): KOGA, Junichiro
!  File : XBSImporter.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.atomcoord.io;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.beans.PropertyChangeListener;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.util.HashMap;
import java.util.Vector;

import javax.swing.JButton;
import javax.swing.JPanel;

import org.apache.log4j.Logger;

import ciss.phase_viewer.atomcoord.Atom;
import ciss.phase_viewer.atomcoord.AtomCoords;
import ciss.phase_viewer.atomcoord.AtomList;
import ciss.phase_viewer.atomcoord.Cell;
import ciss.phase_viewer.mainpanel.InternalFrameChase;

/**
 * XBSプログラム(http://www.ihp-ffo.de/~msm/)で可視化可能なファイルのインポート. FZMDDX固有のセルの処理も行う.
 * 
 * @author
 */
public class XBSImporter implements Importer {
    private Logger logger = Logger.getLogger(XBSImporter.class.getName());

    private String[] frameChoice = { "first frame", "last frame", "all" };
    private String frame = frameChoice[0];

    private final String ATOM = "atom";
    private final String GAMMA = "Gamma";
    private final String C01 = "C01";
    private final String C02 = "C02";
    private final String C03 = "C03";
    private final String FRAME = "frame";

    private final String[] NOT_ELEM_NAME = { "Gamma", "C01", "C02", "C03",
            "C12", "C21", "C13", "C31", "C23", "C32", "C123", "C213", "C321" };

    /** Creates a new instance of XBSImporter */
    public XBSImporter() {
    }

    public AtomCoords[] getAtomCoordsFrom(String fileName) {
        BufferedReader reader = null;
        AtomCoords firstFrame = new AtomCoords();
        firstFrame.setUnit(AtomCoords.ANGSTROM);
        firstFrame.isCart(true);
        try {
            reader = new BufferedReader(new FileReader(fileName));
            String line = "";
            AtomList list = firstFrame.getAtomList();
            String[] avec = null;
            String[] bvec = null;
            String[] cvec = null;
            while ((line = reader.readLine()) != null) {
                line = line.trim();
                if (line.startsWith(ATOM)) {
                    String[] array = line.split("\\s+");
                    if (array == null || array.length < 5) {
                        return null;
                    }
                    boolean isAtom = true;
                    String elemName = array[1];
                    for (int i = 0; i < NOT_ELEM_NAME.length; i++) {
                        if (elemName.equals(NOT_ELEM_NAME[i])) {
                            isAtom = false;
                        }
                    }
                    if (isAtom) {
                        String[] co = new String[] { array[2], array[3],
                                array[4] };
                        Atom atom = new Atom(elemName, co);
                        list.addAtom(atom);
                    }

                    if (elemName.equals(C01) && avec == null) {
                        String C012 = reader.readLine();
                        if (C012 == null) {
                            continue;
                        }
                        String[] ar = C012.trim().split("\\s+");
                        if (ar.length >= 5) {
                            avec = new String[] { ar[2], ar[3], ar[4] };
                            logger.debug("c01: 0: " + ar[0] + " 1: " + ar[1]
                                    + " 2: " + ar[2] + " 3: " + ar[3] + " 4: "
                                    + ar[4]);
                            logger.debug("got avec: " + avec[0] + " " + avec[1]
                                    + " " + avec[2]);
                        }
                    }
                    if (elemName.equals(C02) && bvec == null) {
                        String C022 = reader.readLine();
                        if (C022 == null) {
                            continue;
                        }
                        String[] ar = C022.trim().split("\\s+");
                        if (ar.length >= 5) {
                            bvec = new String[] { ar[2], ar[3], ar[4] };
                            logger.debug("got bvec: " + bvec[0] + " " + bvec[1]
                                    + " " + bvec[2]);
                        }
                    }
                    if (elemName.equals(C03) && cvec == null) {
                        String C032 = reader.readLine();
                        if (C032 == null) {
                            continue;
                        }
                        String[] ar = C032.trim().split("\\s+");
                        if (ar.length >= 5) {
                            cvec = new String[] { ar[2], ar[3], ar[4] };
                            logger.debug("got cvec: " + cvec[0] + " " + cvec[1]
                                    + " " + cvec[2]);
                        }
                    }
                }
            }
            if (avec != null && bvec != null && cvec != null) {
                Cell cell = new Cell(avec, bvec, cvec);
                firstFrame.setCell(cell);
            } else {
                logger.debug("failed to get cell.");
            }
        } catch (IOException ioe) {
            logger.error("failed parse..");
        } finally {
            try {
                reader.close();
            } catch (Exception exc) {
            }
        }

        String dir = new File(fileName).getParent();
        String name = new File(fileName).getName().trim();
        String[] foo = name.split("\\.");
        if (foo.length == 1) {
            return new AtomCoords[] { firstFrame };
        }
        String mvfile_prefix = "";
        for (int i = 0; i < foo.length - 1; i++)
            mvfile_prefix += foo[i];
        String mvfile = dir + System.getProperty("file.separator")
                + mvfile_prefix + ".mv";
        if (!new File(mvfile).exists()) {
            return new AtomCoords[] { firstFrame };
        }

        int numAt = firstFrame.getNumAt();
        String[] elemNames = new String[numAt];
        int numFrame = 0;
        for (int i = 0; i < numAt; i++) {
            elemNames[i] = firstFrame.getAtomList().getAtomAt(i)
                    .getElementName();
        }
        Vector frames = new Vector();
        frames.addElement(firstFrame);

        try {
            reader = new BufferedReader(new FileReader(mvfile));
            String line = "";
            int icount = 0;
            AtomCoords tmpCoords = null;
            while ((line = reader.readLine()) != null) {
                line = line.trim();
                if (line.startsWith(FRAME)) {
                    tmpCoords = new AtomCoords();
                    frames.addElement(tmpCoords);
                    icount = 0;
                    numFrame++;
                    continue;
                }
                String[] array = line.split("\\s+");
                if (array.length < 3) {
                    continue;
                }
                if (icount < numAt) {
                    Atom atom = new Atom(elemNames[icount], new String[] {
                            array[0], array[1], array[2] });
                    tmpCoords.getAtomList().addAtom(atom);
                }
                icount++;

                if (icount == numAt) {
                    String[] avec = null;
                    String[] bvec = null;
                    String[] cvec = null;
                    try {
                        reader.readLine(); // skip two lines.
                        reader.readLine();

                        String av = reader.readLine();
                        reader.readLine();
                        String bv = reader.readLine();
                        reader.readLine();
                        String cv = reader.readLine();
                        avec = av.trim().split("\\s+");
                        bvec = bv.trim().split("\\s+");
                        cvec = cv.trim().split("\\s+");
                    } catch (Exception exp) {
                        ;
                    }
                    if (avec != null && bvec != null && cvec != null) {
                        tmpCoords.setCell(new Cell(avec, bvec, cvec));
                    }
                }
            }
        } catch (Exception exce) {
            logger.error("failed parse: " + mvfile);
            exce.printStackTrace();
        } finally {
            try {
                reader.close();
            } catch (Exception exc) {
            }
        }

        int targetFrame = -1;
        if (select != null) {
            targetFrame = select.getTargetFrame(frames.size());
        }
        if (targetFrame < 0) {
            AtomCoords[] cds = new AtomCoords[frames.size()];
            frames.copyInto(cds);
            return cds;
        }
        return new AtomCoords[] { (AtomCoords) frames.get(targetFrame) };
    }

    public boolean hasOptions() {
        return true;
    }

    public String getType() {
        return "XBS file";
    }

    public javax.swing.filechooser.FileFilter getFileFilter() {
        return new javax.swing.filechooser.FileFilter() {
            public boolean accept(File f) {
                if (f.isDirectory()) {
                    return true;
                }

                String fileName = f.getName().toLowerCase();

                if (fileName != null) {
                    if (fileName.endsWith(".bs") || fileName.endsWith(".BS")) {
                        return true;
                    } else {
                        return false;
                    }
                }
                return false;
            }

            public String getDescription() {
                return "XBS file (*.bs)";
            }
        };
    }

    private PropertyChangeListener listener;

    public void createOptionsPanel(boolean isheavy,
            PropertyChangeListener listener, String fileName) {
        this.listener = listener;
        if (!isheavy) {
            OptionsPanel op = new OptionsPanel();
        } else {
            OptionsPanelHeavy op = new OptionsPanelHeavy();
        }
    }

    class OptionsPanel extends InternalFrameChase {
        OptionsPanel() {
            super("options", true, true, true, true, new java.awt.Dimension(
                    200, 150));
            init();
        }

        private void init() {
            JPanel pchoice = new JPanel();
            select = new FrameCombo();
            pchoice.add(select);

            JPanel btnpanel = new JPanel();
            JButton ok = new JButton("ok");
            btnpanel.add(ok);

            JPanel panel = new JPanel();
            panel.add(pchoice);
            panel.add(btnpanel);

            getContentPane().add(panel);

            ok.addActionListener(new ActionListener() {
                public void actionPerformed(ActionEvent e) {
                    dispose();
                    listener.propertyChange(null);
                }
            });

        }
    }

    private FrameCombo select;

    public void setOptions(HashMap options) {
    }

    public boolean isImportable(String fileName) {
        if (new File(fileName).isDirectory()) {
            return false;
        }
        return getFileFilter().accept(new File(fileName));
    }

    class OptionsPanelHeavy extends InternalFrameChase {
        OptionsPanelHeavy() {
            super("options", new java.awt.Dimension(200, 150));
            init();
        }

        private void init() {
            JPanel pchoice = new JPanel();
            select = new FrameCombo();
            pchoice.add(select);

            JPanel btnpanel = new JPanel();
            JButton ok = new JButton("ok");
            btnpanel.add(ok);

            JPanel panel = new JPanel();
            panel.add(pchoice);
            panel.add(btnpanel);

            getContentPane().add(panel);

            ok.addActionListener(new ActionListener() {
                public void actionPerformed(ActionEvent e) {
                    dispose();
                    listener.propertyChange(null);
                }
            });

            pack();
            setVisible(true);
        }
    }
}
