package Common.Visual.Trees;
import Common.MainModule_;
import Common.Visual.Fonts.VisualiserFonts;
import Common.Visual.Menus.GraphMenu;
import Common.Visual.Themes.ThemeElement;

import javax.swing.*;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.TreePath;
import javax.swing.tree.TreeSelectionModel;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
public class StyledTree extends JTree implements ThemeElement {
    //---------------------------------
    private final GraphMenu menu;
    public DefaultMutableTreeNode root = null;
    //-включение /отключение событий --
    protected boolean events_on = true;
    public StyledTree(DefaultMutableTreeNode root_in) {
        super(root_in);
        root = root_in;
        setOpaque(true);
        setFont(MainModule_.instance.getUI().getTheme().Fonts.get(VisualiserFonts.TreePlain));
        setToggleClickCount(0);  //отключение сворачивание разворачивания по двойному клику
        //--
        if (getRendererClass() != null)
            setCellRenderer(MainModule_.instance.getUI().getTreeRenderer(getRendererClass()));
        //--
        getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION);
        addTreeSelectionListener(e -> {
            if (events_on && e.isAddedPath())
                SelectionAction(e.getPath());
        });
        addMouseListener(new MouseAdapter() {
            @Override
            public void mouseClicked(MouseEvent e) {
                if (e.getClickCount() == 1) {
                    switch ((e.getButton())) {
                        //левая клавиша.
                        case MouseEvent.BUTTON1:
                            if (getSelectionCount() > 0) LeftMouseAction1();
                            break;
                        //колесо
                        case MouseEvent.BUTTON2:
                            break;
                        //правая клавиша
                        case MouseEvent.BUTTON3:
                            if (menu != null)
                                menu.Show(e);
                            break;
                    }
                } else {
                    if (e.getClickCount() == 2) {
                        switch ((e.getButton())) {
                            case MouseEvent.BUTTON1:
                                if (getSelectionCount() > 0) LeftMouseAction2();
                                break;
                        }
                    }
                }
            }
        });
        menu = createMenu();
        applyTheme();
        ExpandAll();
    }
    public Class getRendererClass() {
        return null;
    }
    public void EventsOn() {
        events_on = true;
    }
    public void EventsOff() {
        events_on = false;
    }
    public String getBranchesName() {
        return "";
    }
    public void LeftMouseAction1() {
    }
    public void LeftMouseAction2() {
    }
    public void SelectionAction(TreePath e) {
    }
    @Override
    public void applyTheme() {
        setBackground(MainModule_.instance.getUI().getTheme().trees_background);
        setForeground(MainModule_.instance.getUI().getTheme().foreground);
        menu.applyTheme();
    }
    protected GraphMenu createMenu() {
        return new GraphMenu(this);
    }
    public DefaultMutableTreeNode getNodeByRow(int row) {
        DefaultMutableTreeNode res = null;
        if (row >= 0) {
            TreePath p = getPathForRow(row);
            res = (DefaultMutableTreeNode) p.getLastPathComponent();
        }
        return res;
    }
    protected int getStartLine() {
        return 0;
    }
    public void ExpandAll() {
        for (int i = getStartLine(); i < getRowCount(); ++i)
            expandRow(i);
    }
    public void CollapseAll() {
        for (int i = getRowCount() - 1; i >= getStartLine(); --i) {
            collapseRow(i);
        }
    }
    protected boolean findNode(Object userObject, Object criteria) {
        return true;
    }
    public DefaultMutableTreeNode FindByCriteria(Object criteria) {
        DefaultMutableTreeNode res = root;
        for (int i = 0; i < getRowCount(); ++i) {
            DefaultMutableTreeNode node = getNodeByRow(i);
            if (findNode(node.getUserObject(), criteria)) {
                res = node;
                break;
            }
        }
        return res;
    }
    public TreePath ShowNode(DefaultMutableTreeNode node) {
        TreePath res = new TreePath(((DefaultTreeModel) getModel()).getPathToRoot(node));
        scrollPathToVisible(res);
        return res;
    }
    public TreePath ShowNodeByCriteria(Object criteria) {
        return ShowNode(FindByCriteria(criteria));
    }
    public void SelectNodeByCriteria(Object criteria) {
        EventsOff();
        TreePath res = ShowNodeByCriteria(criteria);
        setSelectionPath(res);
        EventsOn();
    }
    public void SelectNode(DefaultMutableTreeNode node) {
        setSelectionPath(new TreePath(((DefaultTreeModel) getModel()).getPathToRoot(node)));
    }
    //https://stackoverflow.com/questions/7928839/adding-and-removing-nodes-from-a-jtree !!!
    public void AddNode(DefaultMutableTreeNode parent, DefaultMutableTreeNode node) {
        parent.add(node);
        DefaultTreeModel model = (DefaultTreeModel) getModel();
        model.reload(parent);
        //--->>
        TreePath path = new TreePath(model.getPathToRoot(node)); //брать путь к узлу так и только так.иначе не работает.!!
        setSelectionPath(path);
        //scrollPathToVisible(path);
    }
    public void RemoveNode(DefaultMutableTreeNode node) {
        if (node.getParent() != null) {
            DefaultTreeModel model = (DefaultTreeModel) getModel();
            model.removeNodeFromParent(node);
        }
    }
    public void RefreshNode(DefaultMutableTreeNode node) {
        DefaultTreeModel model = (DefaultTreeModel) getModel();
        model.reload(node);
    }
}
