/*
!=======================================================================
!
!  PROGRAM  PHASE-Viewer  (PHASE-Viewer 2014.01 ver.3.3.0)
!
!  Created on 2005/07/12, 20:19
!  AUTHOR(S): KOGA, Junichiro
!  File : ProjectBrowser.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.projectbrowser;

import java.awt.Component;
import java.awt.Container;
import java.awt.Dimension;
import java.io.File;
import java.io.IOException;
import java.io.Serializable;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Vector;

import javax.swing.JMenuBar;
import javax.swing.JSplitPane;
import javax.swing.event.InternalFrameAdapter;
import javax.swing.event.InternalFrameEvent;
import javax.swing.tree.TreePath;

import org.apache.log4j.Logger;
import org.jdom.Document;
import org.jdom.Element;
import org.jdom.JDOMException;
import org.jdom.input.SAXBuilder;

import ciss.phase_viewer.mainpanel.InternalFrameChase;
import ciss.phase_viewer.projectbrowser.projectdirbrowser.ProjectDirBrowser;
import ciss.phase_viewer.projectbrowser.projectdirbrowser.ProjectDirBrowserNode;
import ciss.phase_viewer.projectbrowser.projectstatemanipulator.ProjectStateChangeEvent;
import ciss.phase_viewer.projectbrowser.projectstatemanipulator.ProjectStateChangeListener;

/**
 * 
 * @author KOGA, Junichiro
 */
public class ProjectBrowser extends InternalFrameChase implements
        ProjectStateChangeListener, Serializable {
    private static Logger logger = Logger.getLogger(ProjectBrowser.class
            .getName());
    private String myproj = System.getProperty("user.home")
            + System.getProperty("file.separator") + ".phase-viewer"
            + System.getProperty("file.separator") + "my_projects.xml";
    private JSplitPane splitpane;
    private Document doc;
    private ProjectDirBrowser dirbrowser;
    private ProjectDirBrowserNode associatedNode;
    private Vector projectManipulators = new Vector();
    private ProjectInfo projectInfo;

    public ProjectBrowser(Dimension dim, ProjectInfo projectInfo) {
        super(projectInfo.getProjectName() + " ("
                + projectInfo.getProjectType() + ")", true, true, true, true,
                dim, projectInfo.getProjectType());
        this.projectInfo = projectInfo;
        projectInfo.setParent(this);
        init();
    }

    /**
     * このProjectBrwoserに関連付けられたノードを設定する.
     * 
     * @param このProjectBrowserに関連付けられたノード
     */
    public void setAssociatedNode(ProjectDirBrowserNode node) {
        this.associatedNode = node;
    }

    /**
     * このProjectBrowserに関連付けられたノードを取得する.
     * 
     * @return このProjectBrowserに関連付けられたノード.
     */
    public ProjectDirBrowserNode getAssociatedNode() {
        return this.associatedNode;
    }

    /**
     * ProjectBrowserから, projectのノードを選択する.
     */
    public void selectFromProjects() {
        if (associatedNode == null)
            return;
        associatedNode.getDirBrowser().getTree()
                .scrollPathToVisible(new TreePath(associatedNode.getPath()));
        associatedNode.getDirBrowser().getTree()
                .setSelectionPath(new TreePath(associatedNode.getPath()));
    }

    public void registerProjectManipulators(ProjectManipulator manip) {
        projectManipulators.addElement(manip);
    }

    public boolean isLoaded(Class clazz) {
        String cname = clazz.getName();
        for (int i = 0; i < projectManipulators.size(); i++) {
            String regName = projectManipulators.elementAt(i).getClass()
                    .getName();
            if (regName.equals(cname)) {
                return true;
            }
        }
        return false;
    }

    public ProjectManipulator getProjectManipulator(String cname) {
        for (int i = 0; i < projectManipulators.size(); i++) {
            String regName = projectManipulators.elementAt(i).getClass()
                    .getName();
            if (regName.equals(cname)) {
                return (ProjectManipulator) projectManipulators.elementAt(i);
            }
        }
        return null;
    }

    protected boolean imClosing() {
        boolean ret = true;
        for (int i = 0; i < projectManipulators.size(); i++) {
            Object obj = projectManipulators.elementAt(i);
            if (obj != null) {
                if (((ProjectManipulator) obj).postProcess()) {
                    ret = false;
                }
            }
        }
        return ret;
    }

    public void recreate() {
        setTitle(projectInfo.getProjectName() + " ("
                + projectInfo.getProjectType() + ")");
        Container container = getContentPane();
        Component[] comps = container.getComponents();
        if (comps == null || comps.length == 0) {
            return;
        }
        for (int i = 0; i < comps.length; i++) {
            if (comps[i] != null && comps[i] instanceof ProjectManipulator) {
                ((ProjectManipulator) comps[i]).recreate();
            }
        }
    }

    public void projectStateChanged(ProjectStateChangeEvent e) {
    }

    public ProjectDirBrowser getDirBrowser() {
        return this.dirbrowser;
    }

    private void init() {
        setJMenuBar(new ProjectBrowserMenuBar(this));
        addInternalFrameListener(new InternalFrameListenerProjectBrowser(this));
    }

    public void setProjectManipulator(ProjectManipulator manip) {
        Container container = getContentPane();
        container.removeAll();
        container.add(manip);
    }

    public ProjectDirBrowserNode getRootNode() {
        return dirbrowser.getRootNode();
    }

    public ProjectDirBrowserNode getSelectedNode() {
        return dirbrowser.getSelectedNode();
    }

    public static Document getDocument(File myproj_file) {
        URL myproj_url;
        if (myproj_file.exists()) {
            try {
                myproj_url = new URL("file://localhost/"
                        + myproj_file.getAbsolutePath());
            } catch (MalformedURLException ex) {
                logger.warn("malformed url found. using default.");
                myproj_url = ProjectBrowser.class
                        .getResource("/ciss/phase_viewer/projectbrowser/my_projects.xml");
            }
        } else {
            myproj_url = ProjectBrowser.class
                    .getResource("/ciss/phase_viewer/projectbrowser/my_projects.xml");
        }

        Document docu = createDoc(myproj_url);
        if (docu == null) {
            logger.warn("invalid 'my_projects' file... using default");
            myproj_url = ProjectBrowser.class
                    .getResource("/ciss/phase_viewer/projectbrowser/my_projects.xml");
            docu = createDoc(myproj_url);
        }
        Element root = docu.getRootElement();

        if (!root.getName().equals("projects")) {
            logger.warn("not a valid my_projects file... using default");
            myproj_url = ProjectBrowser.class
                    .getResource("/ciss/phase_viewer/projectbrowser/my_projects.xml");
            docu = createDoc(myproj_url);
        }

        return docu;
    }

    private static Document createDoc(URL url) {
        Document docu = null;
        SAXBuilder builder = new SAXBuilder();
        try {
            docu = builder.build(url);
        } catch (JDOMException jde) {
            logger.error("failed to parse " + url);
            logger.error("unrecoverable error.");
        } catch (IOException ioe) {
            logger.error("failed to parse " + url);
            logger.error("unrecoverable error.");
        }
        logger.debug("doc: " + docu);
        return docu;
    }

}

class ProjectBrowserMenuBar extends JMenuBar {
    private ProjectBrowser parent;
    private Logger logger = Logger.getLogger(ProjectBrowserMenuBar.class
            .getName());

    protected ProjectBrowserMenuBar(ProjectBrowser parent) {
        this.parent = parent;
        createMenu();
    }

    private void createMenu() {
        // MyJMenu file = new MyJMenu("File",KeyEvent.VK_F);
        // MyJMenuItem newproj = new MyJMenuItem("new project", KeyEvent.VK_P);
        // MyJMenuItem newsubproj = new MyJMenuItem("new subproject",
        // KeyEvent.VK_S);
        // MyJMenuItem remproj = new MyJMenuItem("remove project");
        // MyJMenuItem remsubproj = new MyJMenuItem("remove sub project");
        //
        // MyJMenuItem exit = new MyJMenuItem("exit", KeyEvent.VK_X);
        // file.add(newproj);
        // file.add(newsubproj);
        // file.addSeparator();
        // file.add(remproj);
        // file.add(remsubproj);
        // file.addSeparator();
        // file.add(exit);
        // this.add(file);
        //
        // newproj.addActionListener(new ActionListener() {
        // public void actionPerformed(ActionEvent e) {
        // parent.bootProjectCreator();
        //
        // }
        // });
        //
        // newsubproj.addActionListener(new ActionListener() {
        // public void actionPerformed(ActionEvent e) {
        // parent.bootSubProjectCreator();
        // }
        // });
        //
        // remproj.addActionListener(new ActionListener() {
        // public void actionPerformed(ActionEvent e) {
        // parent.bootProjectRemover();
        // }
        // });
        //
        // remsubproj.addActionListener(new ActionListener() {
        // public void actionPerformed(ActionEvent e) {
        // parent.bootSubProjectRemover();
        // }
        // });
        //
        // exit.addActionListener( new ActionListener() {
        // public void actionPerformed(ActionEvent e) {
        // parent.dispose();
        // }
        // });

    }
}

class InternalFrameListenerProjectBrowser extends InternalFrameAdapter {
    private Logger logger = Logger
            .getLogger(InternalFrameListenerProjectBrowser.class.getName());
    private ProjectBrowser parent;

    protected InternalFrameListenerProjectBrowser(ProjectBrowser parent) {
        this.parent = parent;
    }

    public void internalFrameClosing(InternalFrameEvent e) {
        // parent.imClosing();
    }

    public void internalFrameClosed(InternalFrameEvent e) {
        parent.imClosing();
    }
}
