/*
 * FigTreePanel.java
 *
 * Copyright (C) 2006-2014 Andrew Rambaut
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 */

package figtree.application;

import jam.controlpalettes.ControlPalette;
import jam.disclosure.SlideOpenPanel;
import figtree.treeviewer.*;
import figtree.treeviewer.painters.*;

import javax.swing.*;
import javax.swing.plaf.basic.BasicSplitPaneDivider;
import javax.swing.plaf.basic.BasicSplitPaneUI;
import java.awt.*;
import java.lang.reflect.Field;

/**
 * This is a panel that has a TreeViewer and a BasicControlPalette with
 * the default Controllers and Painters.
 *
 * @author Andrew Rambaut
 * @version $Id$
 *
 * $HeadURL$
 *
 * $LastChangedBy$
 * $LastChangedDate$
 * $LastChangedRevision$
 */
public class FigTreePanel extends JPanel {

    public final static int CONTROL_PALETTE_WIDTH = 200;

    public FigTreePanel(JFrame frame, final ExtendedTreeViewer treeViewer, ControlPalette controlPalette) {

        this.treeViewer = treeViewer;
        this.controlPalette = controlPalette;

        // the scrollpane below now has this border
//        controlPalette.getPanel().setBorder(BorderFactory.createMatteBorder(0, 0, 0, 1, Color.GRAY));
        controlPalette.getPanel().setBackground(new Color(231, 237, 246));
        controlPalette.getPanel().setOpaque(true);

        treeViewerController = new TreeViewerController(treeViewer);
        controlPalette.addController(treeViewerController);

        controlPalette.addController(new MultipleTreesController(treeViewer));

        // This controller handles reading/writing of attribute colour schemes but doesn't presently
        // show any UI
        AttributeColourController attributeColourController = new AttributeColourController(treeViewer, frame);
        controlPalette.addController(attributeColourController);

        controlPalette.addController(new TreeAppearanceController(treeViewer, frame, attributeColourController));

        treesController = new TreesController(treeViewer);
        controlPalette.addController(treesController);

        controlPalette.addController(new TimeScaleController(treeViewer));

        // Create a tip label painter and its controller
        final BasicLabelPainter tipLabelPainter = new BasicLabelPainter(BasicLabelPainter.PainterIntent.TIP);
        controlPalette.addController(new LabelPainterController("Tip Labels", "tipLabels", tipLabelPainter, frame, attributeColourController, treeViewer));
        treeViewer.setTipLabelPainter(tipLabelPainter);

        // Create a node label painter and its controller
        final BasicLabelPainter nodeLabelPainter = new BasicLabelPainter(BasicLabelPainter.PainterIntent.NODE);
        nodeLabelPainter.setVisible(false);
        controlPalette.addController(new LabelPainterController("Node Labels", "nodeLabels", nodeLabelPainter, frame, attributeColourController, treeViewer));
        treeViewer.setNodeLabelPainter(nodeLabelPainter);

        // Create a node bar painter and its controller
        final NodeBarPainter nodeBarPainter = new NodeBarPainter();
        nodeBarPainter.setForeground(new Color(24, 32, 228, 128));
        nodeBarPainter.setVisible(false);
        controlPalette.addController(new NodeBarController("Node Bars", nodeBarPainter, treeViewer));
        treeViewer.setNodeBarPainter(nodeBarPainter);

        // Create a node shape painter and its controller
        final NodeShapePainter nodeShapePainter = new NodeShapePainter();
        nodeShapePainter.setVisible(false);
        controlPalette.addController(new NodeShapeController("Node Shapes", nodeShapePainter, attributeColourController, treeViewer));
        treeViewer.setNodeShapePainter(nodeShapePainter);

        // Create a branch label painter and its controller
        final BasicLabelPainter branchLabelPainter = new BasicLabelPainter(BasicLabelPainter.PainterIntent.BRANCH);
        branchLabelPainter.setVisible(false);
        controlPalette.addController(new LabelPainterController("Branch Labels", "branchLabels", branchLabelPainter, frame, attributeColourController, treeViewer));
        treeViewer.setBranchLabelPainter(branchLabelPainter);

        // Create a scale controller
        final ScaleBarPainter scaleBarPainter = new ScaleBarPainter();
        scaleBarPainter.setVisible(true);
        controlPalette.addController(new ScaleBarPainterController(scaleBarPainter, treeViewer));
        treeViewer.addScalePainter(scaleBarPainter);

        // Create a scale axis controller
        final ScaleAxisPainter scaleAxisPainter = new ScaleAxisPainter();
        final ScaleGridPainter scaleGridPainter = new ScaleGridPainter();
        scaleAxisPainter.setVisible(false);
        scaleGridPainter.setVisible(false);
        controlPalette.addController(new ScaleAxisPainterController(scaleAxisPainter, scaleGridPainter, treeViewer));
        treeViewer.addScalePainter(scaleAxisPainter);
        treeViewer.setScaleGridPainter(scaleGridPainter);

        // Create a legend controller
        final LegendPainter legendPainter = new LegendPainter(attributeColourController);
        legendPainter.setVisible(false);
        controlPalette.addController(new LegendPainterController(legendPainter, attributeColourController, treeViewer));
        treeViewer.setLegendPainter(legendPainter);

        slideOpenPanel = new SlideOpenPanel(treeViewer);

        setLayout(new BorderLayout());
//        add(slideOpenPanel, BorderLayout.CENTER);

        JScrollPane scrollPane = new JScrollPane();
        scrollPane.setBorder(BorderFactory.createMatteBorder(0, 0, 0, 1, Color.GRAY));
        scrollPane.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
        scrollPane.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);

        int scrollBarWidth = scrollPane.getVerticalScrollBar().getWidth();
        int controlPanelWidth = CONTROL_PALETTE_WIDTH + scrollBarWidth;
        controlPalette.setPreferredWidth(controlPanelWidth);

        scrollPane.setViewportView(controlPalette.getPanel());
//        add(scrollPane, BorderLayout.WEST);

        JSplitPane splitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, scrollPane, slideOpenPanel);
        splitPane.putClientProperty("Quaqua.SplitPane.style", "bar");
        splitPane.setOneTouchExpandable(true);
        add(splitPane, BorderLayout.CENTER);
        int w = splitPane.getLeftComponent().getPreferredSize().width;
        splitPane.getLeftComponent().setMinimumSize(new Dimension(w, 0));

//        splitPane.getLeftComponent().setMaximumSize(new Dimension(2 * w, 0));

        // Might be possible to improve the action of the oneTouchExpandable button. Ideally would not allow
        // maximization of control panel, only its collapse.
//        BasicSplitPaneDivider bspd = ((BasicSplitPaneUI)splitPane.getUI()).getDivider();
//        try {
//            Field rightButtonField = BasicSplitPaneDivider.class.getDeclaredField("rightButton");
//            rightButtonField.setAccessible(true);
//            JButton rightButton = (JButton) rightButtonField.get(((BasicSplitPaneUI)splitPane.getUI()).getDivider());
//
//            Field leftButtonField = BasicSplitPaneDivider.class.getDeclaredField("leftButton");
//            leftButtonField.setAccessible(true);
//            JButton leftButton = (JButton) leftButtonField.get(((BasicSplitPaneUI)splitPane.getUI()).getDivider());
//
//
//        } catch (Exception e) {
//            e.printStackTrace();
//        }

//        treeViewer.addAnnotationsListener(new AnnotationsListener() {
//            public void annotationsChanged() {
//
//                tipLabelPainter.setupAttributes(treeViewer.getTrees());
//                nodeLabelPainter.setupAttributes(treeViewer.getTrees());
//                nodeBarPainter.setupAttributes(treeViewer.getTrees());
//                branchLabelPainter.setupAttributes(treeViewer.getTrees());
//                legendPainter.setupAttributes(treeViewer.getTrees());
//            }
//        });
    }

    public TreeViewer getTreeViewer() {
        return treeViewer;
    }

    public ControlPalette getControlPalette() {
        return controlPalette;
    }

    public void showUtilityPanel(JPanel utilityPanel) {
        if (utilityPanel == null) {
            return;
        }
		slideOpenPanel.showUtilityPanel(utilityPanel);
    }

	public void hideUtilityPanel() {
		slideOpenPanel.hideUtilityPanel();
	}


	public JPanel getUtilityPanel() {
		return slideOpenPanel.getUtilityPanel();
	}

    public void toggleMidpointRoot() {
        treesController.toggleMidpointRoot();
    }

    public void toggleIncreasingNodeOrder() {
        treesController.toggleIncreasingNodeOrder();
    }

    public void toggleDecreasingNodeOrder() {
        treesController.toggleDecreasingNodeOrder();
    }

    private final TreeViewer treeViewer;
    private final TreeViewerController treeViewerController;
    private final TreesController treesController;
    private final ControlPalette controlPalette;
    private final SlideOpenPanel slideOpenPanel;
}
