/*
!=======================================================================
!
!  PROGRAM  PHASE-Viewer  (PHASE-Viewer 2014.01 ver.3.3.0)
!
!  Created on 2006/12/07 17:02:23
!  AUTHOR(S): KOGA, Junichiro
!  File : CubeExporter.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.beans.PropertyChangeListener;
import java.io.PrintWriter;
import java.util.HashMap;

import javax.swing.filechooser.FileFilter;

import ciss.phase_viewer.atomcoord.Atom;
import ciss.phase_viewer.atomcoord.AtomCoords;
import ciss.phase_viewer.atomcoord.VolumetricData;
import ciss.phase_viewer.common.ConstParameters;
import ciss.phase_viewer.common.ElementInfo;
import ciss.phase_viewer.common.Utils;

public class CubeExporter implements Exporter {
    private org.apache.log4j.Logger logger = org.apache.log4j.Logger
            .getLogger(CubeExporter.class.getName());

    private double ang2bohr = ConstParameters.ANG_2_BOHR;

    /*
     * (non-Javadoc)
     * 
     * @see
     * ciss.phase_viewer.atomcoord.io.Exporter#writeAtomCoordsTo(ciss.phase_viewer
     * .atomcoord.AtomCoords[], java.lang.String)
     */
    public boolean writeAtomCoordsTo(AtomCoords[] coords, String fileName) {
        AtomCoords coord = coords[0];

        coord.convert(AtomCoords.TO_CART, AtomCoords.TO_BOHR);

        PrintWriter writer = Utils.getPrintWriter(fileName);
        writer.println("Gaussian cube file created by the PHASE-Viewer");
        writer.println("volumetric data");

        writer.println(String.valueOf(coord.getNumAt()) + " 0.0 0.0 0.0");
        VolumetricData vdata = coord.getChargeDensity();
        vdata.stripPBC();

        int[] ndiv = vdata.getNumDiv();
        float[][] delta = vdata.getDelta();
        float[] density = vdata.getDensity();
        ElementInfo info = new ElementInfo();

        try {
            for (int i = 0; i < 3; i++)
                writer.println(ndiv[i] + " " + delta[i][0] * ang2bohr + " "
                        + delta[i][1] * ang2bohr + " " + delta[i][2] * ang2bohr);
        } catch (ArrayIndexOutOfBoundsException aobe) {
            logger.error("invalid ndiv and/or delta.");
            return false;
        }

        for (int i = 0; i < coord.getNumAt(); i++) {
            Atom atom = coord.getAtomList().getAtomAt(i);
            if (atom.getDouble() == null || atom.getDouble().length < 3) {
                logger.error("invalid atom pos ");
                return false;
            }
            writer.println(info.getNumberFromSymbol(atom.getElementName())
                    + " " + atom.getNumValenceElectrons() + " "
                    + atom.getDouble()[0] + " " + atom.getDouble()[1] + " "
                    + atom.getDouble()[2]);
        }

        int numRow = density.length / 6;

        for (int i = 0; i < numRow; i++) {
            for (int j = 0; j < 6; j++) {
                writer.print(" " + density[i * 6 + j]);
            }
            writer.print(System.getProperty("line.separator"));
        }

        for (int i = numRow * 6; i < density.length; i++)
            writer.print(" " + density[i]);
        writer.print(System.getProperty("line.separator"));

        writer.flush();
        writer.close();

        vdata.doPBC(density, ndiv);

        return true;
    }

    /*
     * (non-Javadoc)
     * 
     * @see
     * ciss.phase_viewer.atomcoord.io.AtomCoordsIO#createOptionsPanel(boolean)
     */
    public void createOptionsPanel(boolean heavy,
            PropertyChangeListener listener, String fileName) {
    }

    /*
     * (non-Javadoc)
     * 
     * @see ciss.phase_viewer.atomcoord.io.AtomCoordsIO#getFileFilter()
     */
    public FileFilter getFileFilter() {
        return new CubeFileFilter();
    }

    /*
     * (non-Javadoc)
     * 
     * @see ciss.phase_viewer.atomcoord.io.AtomCoordsIO#getType()
     */
    public String getType() {
        return "Gaussian Cube";
    }

    /*
     * (non-Javadoc)
     * 
     * @see ciss.phase_viewer.atomcoord.io.AtomCoordsIO#hasOptions()
     */
    public boolean hasOptions() {
        return false;
    }

    /*
     * (non-Javadoc)
     * 
     * @see
     * ciss.phase_viewer.atomcoord.io.AtomCoordsIO#setOptions(java.util.HashMap)
     */
    public void setOptions(HashMap options) {
    }

}
