package io.xpipe.app.browser.file;

import io.xpipe.app.comp.*;
import io.xpipe.app.comp.base.TextFieldComp;
import io.xpipe.app.platform.InputHelper;
import io.xpipe.app.platform.PlatformThread;

import javafx.beans.property.Property;
import javafx.beans.property.SimpleBooleanProperty;
import javafx.geometry.Pos;
import javafx.scene.control.Button;
import javafx.scene.control.TextField;
import javafx.scene.input.KeyCode;
import javafx.scene.input.KeyCodeCombination;
import javafx.scene.input.KeyCombination;
import javafx.scene.layout.HBox;

import atlantafx.base.theme.Styles;
import org.kordamp.ikonli.javafx.FontIcon;

public class BrowserFileListFilterComp extends RegionStructureBuilder<HBox, BrowserFileListFilterComp.Structure> {

    private final BrowserFileSystemTabModel model;
    private final Property<String> filterString;

    public BrowserFileListFilterComp(BrowserFileSystemTabModel model, Property<String> filterString) {
        this.model = model;
        this.filterString = filterString;
    }

    @Override
    public Structure createBase() {
        var expanded = new SimpleBooleanProperty();
        var text = new TextFieldComp(filterString, false).build();
        var button = new Button();
        RegionDescriptor.builder()
                .nameKey("search")
                .shortcut(new KeyCodeCombination(KeyCode.F, KeyCombination.SHORTCUT_DOWN))
                .build()
                .apply(button);
        button.minWidthProperty().bind(button.heightProperty());
        InputHelper.onExactKeyCode(text, KeyCode.ESCAPE, true, keyEvent -> {
            if (!expanded.get()) {
                return;
            }

            text.clear();
            button.fire();
            keyEvent.consume();
        });
        text.focusedProperty().addListener((observable, oldValue, newValue) -> {
            if (!newValue && filterString.getValue() == null) {
                if (button.isFocused()) {
                    return;
                }

                expanded.set(false);
            }
        });
        filterString.addListener((observable, oldValue, newValue) -> {
            PlatformThread.runLaterIfNeeded(() -> {
                if (newValue == null && !text.isFocused()) {
                    expanded.set(false);
                }
            });
        });
        text.setMinWidth(0);
        Styles.toggleStyleClass(text, Styles.LEFT_PILL);

        filterString.subscribe(val -> {
            PlatformThread.runLaterIfNeeded(() -> {
                if (val == null) {
                    text.getStyleClass().remove(Styles.SUCCESS);
                } else {
                    text.getStyleClass().add(Styles.SUCCESS);
                }
            });
        });

        var fi = new FontIcon("mdi2m-magnify");
        button.setGraphic(fi);
        button.setOnAction(event -> {
            if (model.getCurrentDirectory() == null) {
                return;
            }

            if (expanded.get()) {
                if (filterString.getValue() == null) {
                    expanded.set(false);
                }
                event.consume();
            } else {
                expanded.set(true);
                text.requestFocus();
                event.consume();
            }
        });

        var box = new HBox(text, button);
        box.getStyleClass().add("browser-filter");
        box.setAlignment(Pos.CENTER);

        text.setPrefWidth(0);
        text.setFocusTraversable(false);
        button.getStyleClass().add(Styles.FLAT);
        button.disableProperty().bind(model.getInOverview());
        expanded.addListener((observable, oldValue, val) -> {
            if (val) {
                text.setPrefWidth(250);
                text.setFocusTraversable(true);
            } else {
                text.setPrefWidth(0);
                text.setFocusTraversable(false);
            }
        });
        button.minHeightProperty().bind(text.heightProperty());
        button.minWidthProperty().bind(text.heightProperty());
        button.maxHeightProperty().bind(text.heightProperty());
        button.maxWidthProperty().bind(text.heightProperty());
        return new Structure(box, text, button);
    }

    public record Structure(HBox box, TextField textField, Button toggleButton) implements RegionStructure<HBox> {

        @Override
        public HBox get() {
            return box;
        }
    }
}
