/*
!=======================================================================
!
!  PROGRAM  PHASE-Viewer  (PHASE-Viewer 2014.01 ver.3.3.0)
!
!  Created on 2005/08/12, 13:36
!  AUTHOR(S): KOGA, Junichiro
!  File : ProjectManipulatorSubSelector.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.Dimension;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.IOException;
import java.net.URL;
import java.util.List;
import java.util.Vector;

import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JPanel;
import javax.swing.JSplitPane;
import javax.swing.SwingConstants;
import javax.swing.UIManager;

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.jdom.MyElement;
import ciss.phase_viewer.main.PluginLoader;
import ciss.phase_viewer.mainpanel.LookandFeel;

/**
 * 
 * @author KOGA, Junichiro
 */
public class ProjectManipulatorSubSelector extends JPanel {
    private static Logger logger = Logger
            .getLogger(ProjectManipulatorSubSelector.class.getName());
    private URL property;
    private ProjectInfo info;
    private JSplitPane splitpane;

    private Dimension defaultPreferredSize = new Dimension(80, 30);
    private boolean setInitialPanel = true;

    private Vector projectManipulators = new Vector();

    public static final int VERTICAL = 0;
    public static final int HORIZONTAL = 1;
    private int layout = VERTICAL;

    /**
     * Creates a new instance of ProjectManipulatorSubSelector.
     * 
     * @param property
     *            an xml file which specifies the behavior of this class.
     * @param info
     *            the ProjectInfo object, which encapsulates the necessary
     *            information of the project.
     * @param splitpane
     *            the JSplitPane to which the new ProjectManipulator object is
     *            to be added.
     */
    public ProjectManipulatorSubSelector(URL property, ProjectInfo info,
            JSplitPane splitpane) {
        super();
        this.property = property;
        this.info = info;
        this.splitpane = splitpane;
        parseAndAddButtons();
    }

    /**
     * Creates a new instance of ProjectManipulatorSubSelector.
     * 
     * @param property
     *            an xml file which specifies the behavior of this class.
     * @param info
     *            the ProjectInfo object, which encapsulates the necessary
     *            information of the project.
     * @param splitpane
     *            the JSplitPane to which the new ProjectManipulator object is
     *            to be added.
     * @param setInitialPanel
     *            if true(default), will initially show the first panel written
     *            in @param propery
     */
    public ProjectManipulatorSubSelector(URL property, ProjectInfo info,
            JSplitPane splitpane, boolean setInitialPanel) {
        super();
        this.property = property;
        this.info = info;
        this.splitpane = splitpane;
        this.setInitialPanel = setInitialPanel;
        parseAndAddButtons();
    }

    private void parseAndAddButtons() {
        Document doc = null;
        SAXBuilder builder = new SAXBuilder();
        try {
            doc = builder.build(property);
        } catch (JDOMException jde) {
            logger.error("failed to parse " + property);
            logger.error("unrecoverable error.");
        } catch (IOException ioe) {
            logger.error("failed to parse " + property);
            logger.error("unrecoverable error.");
        }

        Element elem = doc.getRootElement();
        if (!elem.getName().equals("root")) {
            logger.error("invalid ProjectSpecification file.");
            return;
        }

        try {
            String strlayout = elem.getChildTextTrim("layout");
            if (strlayout.equalsIgnoreCase("horizontal")) {
                layout = HORIZONTAL;
            }
        } catch (Exception exc) {
        }

        List list = elem.getChild("subselectors").getChildren();
        int nbuttons = list.size();
        if (layout == VERTICAL) {
            setLayout(new GridLayout(nbuttons, 1));
        } else {
            setLayout(new GridLayout(1, nbuttons));
        }
        SubSelectorButton btn0 = null;
        for (int i = 0; i < nbuttons; i++) {
            Element btn = (Element) list.get(i);
            String name = btn.getChildTextTrim("name");
            String iconpath = btn.getChildTextTrim("iconpath");
            String loadClass = btn.getChildTextTrim("loadclass");
            String description = MyElement.decode(btn
                    .getChildTextTrim("description"));
            SubSelectorButton button = new SubSelectorButton(name, iconpath,
                    description, loadClass, info, splitpane, this);

            String size = btn.getChildTextTrim("size");
            String[] sizes = size.split("x");
            if (sizes == null || sizes.length < 2) {
                button.setPreferredSize(defaultPreferredSize);
            } else {
                int width = 0;
                int height = 0;
                try {
                    width = Integer.parseInt(sizes[0]);
                    height = Integer.parseInt(sizes[1]);
                    button.setPreferredSize(new Dimension(width, height));
                    button.setMinimumSize(new Dimension(width, height));
                    button.setMaximumSize(new Dimension(width, height));
                } catch (NumberFormatException nfe) {
                    button.setPreferredSize(defaultPreferredSize);
                }
            }
            add(button);
            if (i == 0 && setInitialPanel) {
                btn0 = button;
            }
        }

        if (btn0 != null) {
            btn0.bootProjectManipulatorSub();
        }

    }

    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;
    }

    public Vector getProjectManipulators() {
        return projectManipulators;
    }

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

    public int getLayoutPolicy() {
        return layout;
    }

}

class SubSelectorButton extends JButton implements ActionListener {
    private Logger logger = Logger.getLogger(SubSelectorButton.class.getName());
    private String loadClass;
    private ProjectInfo info;
    private JSplitPane splitpane;
    private ProjectManipulatorSubSelector subSelector;

    protected SubSelectorButton(String name, String iconpath,
            String description, String loadClass, ProjectInfo info,
            JSplitPane splitpane, ProjectManipulatorSubSelector subSelector) {
        super(name);
        this.info = info;
        this.loadClass = loadClass;
        this.splitpane = splitpane;
        this.subSelector = subSelector;
        // set icon to button, if iconpath is specified.
        if (iconpath != null && iconpath.length() != 0
                && !iconpath.equals("null")) {
            logger.debug("iconpath: " + iconpath);
            PluginLoader loader = new PluginLoader();
            URL res = null;
            super.setHorizontalTextPosition(SwingConstants.CENTER);
            super.setVerticalTextPosition(SwingConstants.BOTTOM);
            // super.setContentAreaFilled(false);
            if (UIManager.getLookAndFeel().getClass().getName()
                    .equals(LookandFeel.landf_metal))
                super.setContentAreaFilled(false);
            try {
                res = loader.getResource(iconpath.trim());
                super.setIcon(new ImageIcon(res));
            } catch (Exception ex) {
                logger.error("failed to resolve icon path.");
            }
            super.revalidate();
        }
        if (description != null && description.length() != 0) {
            super.setToolTipText(description);
        }
        super.addActionListener(this);
    }

    public void actionPerformed(ActionEvent e) {
        bootProjectManipulatorSub();
    }

    protected void bootProjectManipulatorSub() {
        logger.debug("loadClass: " + loadClass);
        ProjectManipulator manip = null;
        try {
            PluginLoader loader = new PluginLoader();
            Class cla = loader.loadClass(loadClass);
            manip = subSelector.getProjectManipulator(cla.getName());
        } catch (Exception exc) {
            exc.printStackTrace();
        }

        if (manip == null) {
            manip = (ProjectManipulator) PluginLoader.instantiate(loadClass,
                    new Object[] { info });
            manip.init();
            subSelector.registerProjectManipulators(manip);
        }

        if (manip != null)
            manip.buttonPressed();

        boolean post = true;
        try {
            Vector manips = subSelector.getProjectManipulators();

            for (int i = 0; i < manips.size(); i++) {
                if (!((ProjectManipulator) manips.elementAt(i)).postProcess()) {
                    post = false;
                }
            }
        } catch (ClassCastException cce) {
        }

        // if any of the post processes "failed" for some reason, the new
        // component will not be shown.
        if (post) {
            if (subSelector.getLayoutPolicy() == ProjectManipulatorSubSelector.VERTICAL) {
                splitpane.setRightComponent(manip);
            } else {
                splitpane.setBottomComponent(manip);
            }
            manip.componentSet();
        } else {
            logger.info("operation canceled.");
        }

        if (manip != null) {
            manip.postInit();
        }

    }
}
