/*
 * Copyright (c) 2002-2007 TeamDev Ltd. All rights reserved.
 *
 * Use is subject to license terms.
 *
 * The complete licence text can be found at
 * http://www.teamdev.com/winpack/license.jsf
 */
package com.jniwrapper.win32.ie.samples.demo;

import com.jniwrapper.win32.ie.samples.demo.components.LineBevel;
import org.w3c.dom.Node;

import javax.swing.*;
import javax.swing.event.TreeSelectionEvent;
import javax.swing.event.TreeSelectionListener;
import javax.swing.tree.TreeModel;
import javax.swing.tree.TreePath;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

/**
 * This panel is designed to display DOM structure.
 */
class DOMStructurePanel extends JPanel implements TreeSelectionListener
{
    private static final String PAGE_NODE_INFO = "Node";
    private static final String PAGE_TEXT = "Text";

    private JSplitPane _splitPane;
    private JTree _nodeTree;
    private JTable _attrTable;
    private TreeModel _nodeTreeModel;
    private NodeDetailsTableModel _attrTableModel;
    private Node _rootNode;

    private DOMNodeInfoPanel _domNodeInfoPanel;
    private TextAreaPanel _textAreaPanel;

    private JPanel _detailsPanel;
    private CardLayout _detailsPanelLayout;

    private boolean _onlySpecified = true;

    public DOMStructurePanel()
    {
        initialize();
        setBorder(null);
    }

    public void setDocument(Node node)
    {
        _rootNode = node;
        _nodeTreeModel = new DOMNodeTreeModel(_rootNode);
        _nodeTree.setModel(_nodeTreeModel);
        _attrTableModel.setOnlySpecified(_onlySpecified);
        _attrTable.revalidate();
        _attrTable.repaint();
    }

    public void initialize()
    {
        setLayout(new BorderLayout());

        _nodeTreeModel = new DOMNodeTreeModel(null);

        _nodeTree = new JTree(_nodeTreeModel)
        {
            protected void setExpandedState(TreePath path, boolean state)
            {
                if (state)
                {
                    final Cursor waitCursor = Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR);
                    final Cursor defCursor = getCursor();
                    try
                    {
                        setCursor(waitCursor);
                        super.setExpandedState(path, state);
                    }
                    finally
                    {
                        setCursor(defCursor);
                    }
                }
                else
                    super.setExpandedState(path, state);
            }
        };
        _nodeTree.setRootVisible(true);
        _nodeTree.addTreeSelectionListener(this);
        _nodeTree.setCellRenderer(new TreeCellRenderer());
        _nodeTree.setBorder(null);

        _attrTableModel = new DOMAttributeTableModel();
        _attrTableModel.setOnlySpecified(_onlySpecified);

        _attrTable = new JTable(_attrTableModel);
        _attrTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
        _attrTable.setRowSelectionAllowed(true);
        _attrTable.setShowHorizontalLines(false);
        _attrTable.setShowVerticalLines(false);

        _detailsPanelLayout = new CardLayout();
        _detailsPanel = new JPanel(_detailsPanelLayout);

        _domNodeInfoPanel = new DOMNodeInfoPanel();
        _textAreaPanel = new TextAreaPanel();

        _detailsPanel.add(_domNodeInfoPanel, PAGE_NODE_INFO);
        _detailsPanel.add(_textAreaPanel, PAGE_TEXT);

        JScrollPane treeScrollPane = new JScrollPane(_nodeTree);
        treeScrollPane.setBorder(null);
        treeScrollPane.setPreferredSize(new Dimension(90, 1)); //+++

        _splitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, true, treeScrollPane, _detailsPanel);
        _splitPane.setBorder(null);
        add(_splitPane, BorderLayout.CENTER);

        _splitPane.setDividerSize(2);
        _splitPane.setResizeWeight(0.5);
    }

    public void valueChanged(TreeSelectionEvent e)
    {
        TreePath path = e.getPath();
        DOMNodeTreeNode node = (DOMNodeTreeNode)path.getPathComponent(path.getPathCount() - 1);
        final Node browserNode = node.getBrowserNode();

        if (node.getText() != null)
        {
            _textAreaPanel.getTextPane().setText(node.getText());
            _detailsPanelLayout.show(_detailsPanel, PAGE_TEXT);
        }
        else if (isTextNode(browserNode))
        {
            _textAreaPanel.getTextPane().setText(browserNode.getNodeValue());
            _detailsPanelLayout.show(_detailsPanel, PAGE_TEXT);
        }
        else
        {
            if (browserNode != null)
            {
                _domNodeInfoPanel._fieldName.setText(browserNode.getNodeName());
                _domNodeInfoPanel._fieldType.setText("" + browserNode.getNodeType());
                _attrTableModel.setBrowserNode(browserNode);
                _attrTable.revalidate();
                _attrTable.repaint();
            }
            _detailsPanelLayout.show(_detailsPanel, PAGE_NODE_INFO);
        }
    }

    private static boolean isTextNode(Node node)
    {
        if (node == null)
        {
            return false;
        }
        switch (node.getNodeType())
        {
            case Node.TEXT_NODE:
            case Node.COMMENT_NODE:
                return true;
            default:
                return false;
        }
    }

    JTree getTree()
    {
        return _nodeTree;
    }

    class DOMNodeInfoPanel extends JPanel
    {
        JTextField _fieldName;
        JTextField _fieldType;

        public DOMNodeInfoPanel()
        {
            setLayout(new GridBagLayout());
            setBorder(null);

            JLabel title = new JLabel("DOM Node");
            title.setFocusable(false);
            title.setBorder(null);

            add(title, new GridBagConstraints(0, 0, 2, 1, 1.0, 0.0
                    , GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(0, 5, 0, 0), 0, 0));

            add(new LineBevel(), new GridBagConstraints(0, 1, 2, 1, 1.0, 0.0
                    , GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(0, 0, 2, 0), 0, 0));

            final JComboBox filters = new JComboBox(new Object[]{"Specified", "All"});
            filters.addActionListener(new ActionListener()
            {
                public void actionPerformed(ActionEvent e)
                {
                    _onlySpecified = filters.getSelectedIndex() == 0;
                    _attrTableModel.setOnlySpecified(_onlySpecified);
                    _attrTable.repaint();
                    _attrTable.revalidate();
                }
            });

            add(new JLabel("Name:"), new GridBagConstraints(0, 2, 1, 1, 0.0, 0.0
                    , GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(0, 5, 0, 0), 0, 0));

            _fieldName = new JTextField();
            _fieldName.setEditable(false);
            add(_fieldName, new GridBagConstraints(1, 2, 1, 1, 0.0, 0.0
                    , GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(0, 0, 0, 5), 0, 0));


            add(new JLabel("Type:"), new GridBagConstraints(0, 3, 1, 1, 0.0, 0.0
                    , GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(1, 5, 0, 0), 0, 0));

            _fieldType = new JTextField();
            _fieldType.setEditable(false);
            add(_fieldType, new GridBagConstraints(1, 3, 1, 1, 0.0, 0.0
                    , GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(1, 0, 0, 5), 0, 0));

            add(new JLabel("Attributes:"), new GridBagConstraints(0, 4, 1, 1, 0.0, 0.0
                    , GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(1, 4, 0, 0), 0, 0));

            add(filters, new GridBagConstraints(1, 4, 1, 1, 0.0, 0.0
                    , GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(1, 0, 0, 5), 0, 0));

            JScrollPane attributesPane = new JScrollPane();
            JViewport viewport = new JViewport();
            viewport.add(_attrTable);
            viewport.setBackground(Color.white);
            attributesPane.setViewport(viewport);
            attributesPane.setPreferredSize(new Dimension(10, 10));

            add(attributesPane, new GridBagConstraints(0, 5, 2, 1, 1.0, 1.0
                    , GridBagConstraints.WEST, GridBagConstraints.BOTH, new Insets(2, 5, 5, 5), 0, 0));
        }
    }

    class TextAreaPanel extends JPanel
    {
        private JTextPane _textArea;

        public TextAreaPanel()
        {
            setLayout(new BorderLayout());
            _textArea = new JTextPane();
            _textArea.setBorder(BorderFactory.createMatteBorder(5, 5, 5, 5, getBackground()));
            _textArea.setEditable(false);
            add(_textArea, BorderLayout.CENTER);
        }

        public JTextPane getTextPane()
        {
            return _textArea;
        }
    }
}