/*
!=======================================================================
!
!  PROGRAM  PHASE-Viewer  (PHASE-Viewer 2014.01 ver.3.3.0)
!
!  Created on 2006/02/22, 19:14
!  AUTHOR(S): KOGA, Junichiro
!  File : EpsilonInitializer.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.projectmanipulator.uvsorepsilon;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.util.HashMap;

import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.border.TitledBorder;
import javax.swing.event.InternalFrameAdapter;
import javax.swing.event.InternalFrameEvent;

import org.apache.log4j.Logger;
import org.jdom.Attribute;
import org.jdom.Document;
import org.jdom.Element;

import ciss.phase_viewer.common.ExternalProgramExecuter;
import ciss.phase_viewer.common.Utils;
import ciss.phase_viewer.inputinterface.DataManager;
import ciss.phase_viewer.inputinterface.InputInterface;
import ciss.phase_viewer.jdom.MyElement;
import ciss.phase_viewer.mainpanel.InternalFrameChase;
import ciss.phase_viewer.plugins.projectmanipulator.ekcal.EkcalUtils;
import ciss.phase_viewer.plugins.projectmanipulator.phase.PhaseConstants;
import ciss.phase_viewer.projectbrowser.ProjectBrowserUtils;
import ciss.phase_viewer.projectbrowser.ProjectInfo;
import ciss.phase_viewer.projectbrowser.ProjectManipulator;
import ciss.phase_viewer.projectbrowser.projectdirbrowser.ProjectDirBrowser;
import ciss.phase_viewer.projectbrowser.projectdirbrowser.ProjectDirBrowserNode;
import ciss.phase_viewer.projectbrowser.projectdirbrowser.ProjectDirBrowserNodeChangeEvent;
import ciss.phase_viewer.projectbrowser.projectdirbrowser.ProjectDirBrowserNodeChangeListener;
import ciss.phase_viewer.scripting.scripteditor.ScriptEditorCaller;
import ciss.phase_viewer.scripting.scripteditor.ScriptEditorGUI;

/**
 * UVSOR-EPSILONの計算用ディレクトリーの初期化を行うGUI.
 * 
 * @author
 */
public class EpsilonInitializer extends InternalFrameChase implements
        ProjectDirBrowserNodeChangeListener, ScriptEditorCaller {
    private Logger logger = Logger
            .getLogger(EpsilonInitializer.class.getName());
    private ProjectInfo projectInfo;
    private ProjectManipulator parent;
    private ProjectDirBrowserNode node;

    /** Creates a new instance of EpsilonInitializer */
    public EpsilonInitializer(ProjectInfo projectInfo,
            ProjectManipulator parent, ProjectDirBrowserNode node) {
        super("set initial condition for uvsor-epsilon", true, true, true,
                true, new Dimension(350, 350));
        this.projectInfo = projectInfo;
        this.parent = parent;
        this.node = node;
        init();
    }

    private boolean rem = true;
    private JTextField tfPath;
    private JButton ok;
    private JLabel msg;
    private JButton btninit;

    private void init() {
        EkcalUtils.initScript(projectInfo.getProjectDirectory(),
                EkcalUtils.EPSILON);

        Container container = getContentPane();
        container.setLayout(new BoxLayout(container, BoxLayout.Y_AXIS));
        tfPath = new JTextField(40);
        JPanel ppath = new JPanel();
        ppath.setBorder(new TitledBorder("parent directory"));
        ppath.setLayout(new BoxLayout(ppath, BoxLayout.X_AXIS));
        ppath.add(tfPath);

        JPanel pbtns = new JPanel();
        pbtns.setLayout(new BoxLayout(pbtns, BoxLayout.X_AXIS));
        msg = new JLabel("select a valid phase dir");
        msg.setForeground(Color.red);
        ok = new JButton("ok");
        ok.setEnabled(false);

        JPanel pcombo = new JPanel();
        pcombo.setBorder(new TitledBorder("initial condition"));
        btninit = new JButton("edit");
        btninit.setEnabled(false);
        pcombo.add(btninit);

        ProjectDirBrowser browser = new ProjectDirBrowser("projects",
                new ProjectDirBrowserNodeChangeListener[] { this });

        ProjectInfo info = browser.getSelectedProject();
        if (info != null && info.getInfoType() == ProjectInfo.SUB) {
            tfPath.setText(info.getProjectDirectory());
        }

        JPanel ppp = new JPanel();
        ppp.setLayout(new BorderLayout());
        ppp.add(msg, BorderLayout.CENTER);
        ppp.add(ok, BorderLayout.EAST);

        JButton cancel = new JButton("cancel");
        pbtns.add(ppp);
        pbtns.add(cancel);

        ok.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent ae) {
                rem = false;
                dispose();
                createProject();
            }
        });

        cancel.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                dispose();
            }
        });

        btninit.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent ae) {
                bootScrEditor();
            }
        });

        addInternalFrameListener(new InternalFrameAdapter() {
            public void internalFrameClosed(InternalFrameEvent e) {
                if (rem)
                    ProjectBrowserUtils.remove(node);
            }
        });

        container.add(browser);
        container.add(ppath);
        container.add(pcombo);
        container.add(pbtns);
    }

    private void bootScrEditor() {
        ScriptEditorGUI editor = new ScriptEditorGUI(this);
    }

    public String getScriptPath() {
        return EkcalUtils.getScriptPath(projectInfo.getProjectDirectory(),
                EkcalUtils.EPSILON);
    }

    private String parentdir;

    private void createProject() {
        String projdir = projectInfo.getProjectDirectory();
        parentdir = tfPath.getText();
        logger.debug("relative dir from " + projdir + " to " + parentdir + ":");
        String relativeDir = Utils.getRelativePath(projdir, parentdir);
        if (relativeDir == null) {
            logger.error("invalid dir: " + parentdir);
        }
        logger.debug(relativeDir);
        projectInfo.setParentDir(relativeDir);
        Element elem = projectInfo.getProjectElement();
        Element element = new Element("associated_directory");
        element.setAttribute(new Attribute("type", "parent"));
        element.setText(MyElement.encode(relativeDir));
        elem.addContent(element);

        F_INP = EkcalUtils.initializeFileNamesData(projectInfo, parentdir);
        initializeInput(parentdir);
        initializeChaseXML();

        ProjectDirBrowser.saveMyProjectsDocument();
        node.selectMe();

        projectInfo.getInputDataManager().registerToFileStateObserver();
    }

    private String F_INP = "nfinp.data";
    private InputInterface inputInterface;

    private void initializeInput(String phaseDir) {
        String curnfinp = projectInfo.getProjectDirectory()
                + System.getProperty("file.separator") + F_INP;
        String phaseinp = phaseDir + System.getProperty("file.separator")
                + F_INP;
        if (!new File(phaseinp).exists()) {
            logger.error("input file for PHASE doesn't exist.");
            return;
        }

        try {
            ExternalProgramExecuter.copyBinary(phaseinp, curnfinp);
        } catch (Exception exc) {
            logger.error("failed to copy input file: " + phaseinp + " to "
                    + curnfinp);
            exc.printStackTrace();
            return;
        }

        java.net.URL url = PhaseConstants.TABLESPEC;
        DataManager dm = new DataManager(curnfinp, url, false);
        dm.parse();
        inputInterface = dm.getInputInterface();

        EkcalUtils.runInitScript(projectInfo.getProjectDirectory(), phaseDir,
                inputInterface, EkcalUtils.EPSILON);
    }

    private void initializeChaseXML() {
        logger.debug("initializing phase-viewer.xml");
        java.net.URL defchaseXML = getClass()
                .getResource(
                        "/ciss/phase_viewer/plugins/projectmanipulator/phase/phase-viewer.xml");
        Document doc = ciss.phase_viewer.jdom.XMLUtils
                .getDocumentFromURL(defchaseXML);
        String projchaseXML = projectInfo.getProjectDirectory()
                + System.getProperty("file.separator") + "phase-viewer.xml";
        logger.debug("xml: " + projchaseXML);

        EkcalUtils.inheritHostInfo(parentdir, doc);

        ciss.phase_viewer.jdom.XMLUtils.saveDocumentTo(doc, new File(
                projchaseXML));
    }

    public void nodeSelected(ProjectDirBrowserNodeChangeEvent e) {
        if (e == null || e.getSource() == null) {
            return;
        }
        ProjectDirBrowserNode node = (ProjectDirBrowserNode) e.getSource();
        ProjectInfo proj = node.getProjectInfo();
        tfPath.setText(proj.getProjectDirectory());

        boolean isphase = EkcalUtils.isPhaseDir(proj);
        ok.setEnabled(isphase);
        btninit.setEnabled(isphase);
        if (isphase) {
            msg.setText("");
        } else {
            msg.setText("select a valid phase dir");
        }
    }

    public HashMap getObjects() {
        HashMap map = new HashMap();
        String parDir = projectInfo.getProjectDirectory();
        if (!parDir.endsWith(System.getProperty("file.separator")))
            parDir += System.getProperty("file.separator");
        String nfinp = Utils.getFileName("F_INP", parDir);
        if (inputInterface == null) {
            java.net.URL url = PhaseConstants.TABLESPEC;
            DataManager dm = new DataManager(parDir + nfinp, url, false);
            dm.parse();
            inputInterface = dm.getInputInterface();
        }
        map.put("projectInfo", projectInfo);
        map.put("inputInterface", inputInterface);
        return map;
    }
}
