package ctbrec.ui.settings.api;

import static java.util.Optional.*;

import javafx.scene.Node;
import javafx.scene.control.Control;
import javafx.scene.control.Label;
import javafx.scene.control.TextInputControl;
import javafx.scene.control.Tooltip;
import javafx.scene.layout.Pane;

class HighlightingSupport {

    private static final String CSS_HIGHLIGHT_CLASS = "setting-highlighted";

    private HighlightingSupport() {}

    static void highlightMatches(Category cat, String filter) {
        Node node = cat.getGuiOrElse(Label::new);
        highlightMatchess(node, filter);
        if(cat.hasSubCategories()) {
            for (Category sub : cat.getSubCategories()) {
                highlightMatches(sub, filter);
            }
        }
    }

    static void highlightMatchess(Node node, String filter) {
        boolean contains = false;
        if (node instanceof Pane) {
            Pane pane = (Pane) node;
            for (Node child : pane.getChildren()) {
                highlightMatchess(child, filter);
            }
        }

        if (node instanceof Label) {
            Label lbl = (Label) node;
            contains |= lbl.getText().toLowerCase().contains(filter);
            contains |= ofNullable(lbl.getTooltip()).map(Tooltip::getText).orElse("").toLowerCase().contains(filter);
            contains |= labelControlContains(lbl, filter);

            if (contains) {
                if (!node.getStyleClass().contains(CSS_HIGHLIGHT_CLASS)) {
                    node.getStyleClass().add(CSS_HIGHLIGHT_CLASS);
                }
            } else {
                node.getStyleClass().remove(CSS_HIGHLIGHT_CLASS);
            }
        }
    }

    private static boolean labelControlContains(Label lbl, String filter) {
        boolean contains = false;
        if (lbl.labelForProperty().get() != null) {
            Node labeledNode = lbl.labelForProperty().get();
            contains |= labeledNode.toString().toLowerCase().contains(filter);
            if (labeledNode instanceof Control) {
                contains |= ofNullable(((Control) labeledNode).getTooltip()).map(Tooltip::getText).orElse("").toLowerCase().contains(filter);
            }
            if (labeledNode instanceof TextInputControl) {
                contains |= ofNullable(((TextInputControl) labeledNode).getText()).orElse("").toLowerCase().contains(filter);
            }
        }
        return contains;
    }

    static void removeHighlights(Category cat) {
        Node node = cat.getGuiOrElse(Label::new);
        removeHighlights(node);
        if(cat.hasSubCategories()) {
            for (Category sub : cat.getSubCategories()) {
                removeHighlights(sub);
            }
        }
    }

    static void removeHighlights(Node gui) {
        if (gui != null) {
            if (gui instanceof Pane) {
                Pane p = (Pane) gui;
                for (Node n : p.getChildren()) {
                    removeHighlights(n);
                }
            }
            gui.getStyleClass().remove(CSS_HIGHLIGHT_CLASS);
        }
    }
}
