package org.jabref.gui.entryeditor;

import javafx.geometry.HPos;
import javafx.geometry.Pos;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.ProgressIndicator;
import javafx.scene.control.Tooltip;
import javafx.scene.layout.ColumnConstraints;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.HBox;
import javafx.scene.layout.Priority;
import javafx.scene.layout.RowConstraints;
import javafx.scene.layout.VBox;
import javafx.scene.text.Text;

import org.jabref.gui.DialogService;
import org.jabref.gui.LibraryTab;
import org.jabref.gui.StateManager;
import org.jabref.gui.icon.IconTheme;
import org.jabref.gui.preferences.GuiPreferences;
import org.jabref.gui.texparser.CitationsDisplay;
import org.jabref.gui.util.DirectoryMonitor;
import org.jabref.logic.l10n.Localization;
import org.jabref.model.entry.BibEntry;

import com.tobiasdiez.easybind.EasyBind;

public class LatexCitationsTab extends EntryEditorTab {

    private final StateManager stateManager;

    private final LatexCitationsTabViewModel viewModel;

    private final GridPane searchPane;
    private final ProgressIndicator progressIndicator;
    private final CitationsDisplay citationsDisplay;

    public LatexCitationsTab(GuiPreferences preferences,
                             DialogService dialogService,
                             StateManager stateManager,
                             DirectoryMonitor directoryMonitor) {
        this.stateManager = stateManager;

        this.viewModel = new LatexCitationsTabViewModel(
                preferences,
                dialogService,
                directoryMonitor);

        this.searchPane = new GridPane();
        this.progressIndicator = new ProgressIndicator();
        this.citationsDisplay = new CitationsDisplay();

        setText(EntryEditorTabModel.BuiltIn.LATEX_CITATIONS.displayName());
        setTooltip(new Tooltip(Localization.lang("Search citations for this entry in LaTeX files")));
        setGraphic(IconTheme.JabRefIcons.LATEX_CITATIONS.getGraphicNode());
        setSearchPane();
    }

    private void setSearchPane() {
        progressIndicator.setMaxSize(100, 100);

        citationsDisplay.basePathProperty().bindBidirectional(viewModel.directoryProperty());
        citationsDisplay.setItems(viewModel.getCitationList());
        citationsDisplay.setOnMouseClicked(event -> viewModel.handleMouseClick(event, citationsDisplay));

        RowConstraints mainRow = new RowConstraints();
        mainRow.setVgrow(Priority.ALWAYS);

        RowConstraints bottomRow = new RowConstraints(40);
        bottomRow.setVgrow(Priority.NEVER);

        ColumnConstraints column = new ColumnConstraints();
        column.setPercentWidth(100);
        column.setHalignment(HPos.CENTER);

        searchPane.getColumnConstraints().setAll(column);
        searchPane.getRowConstraints().setAll(mainRow, bottomRow);
        searchPane.setId("citationsPane");
        setContent(searchPane);

        HBox latexDirectoryBox = getLatexDirectoryBox();
        VBox citationsPane = getCitationsPane();
        VBox notFoundPane = getNotFoundPane();
        VBox errorPane = getErrorPane();

        EasyBind.subscribe(viewModel.statusProperty(), status -> {
            searchPane.getChildren().clear();
            switch (status) {
                case IN_PROGRESS:
                    searchPane.add(progressIndicator, 0, 0);
                    break;
                case CITATIONS_FOUND:
                    searchPane.add(citationsPane, 0, 0);
                    break;
                case NO_RESULTS:
                    searchPane.add(notFoundPane, 0, 0);
                    break;
                case ERROR:
                    searchPane.add(errorPane, 0, 0);
                    break;
            }
            searchPane.add(latexDirectoryBox, 0, 1);
        });
    }

    private HBox getLatexDirectoryBox() {
        Text latexDirectoryText = new Text(Localization.lang("Current search directory:"));
        Text latexDirectoryPath = new Text();
        latexDirectoryPath.textProperty().bind(viewModel.directoryProperty().asString());
        latexDirectoryPath.getStyleClass().add("latex-citations-directory-path");
        Button latexDirectoryButton = new Button(Localization.lang("Set LaTeX file directory"));
        latexDirectoryButton.setGraphic(IconTheme.JabRefIcons.LATEX_FILE_DIRECTORY.getGraphicNode());
        latexDirectoryButton.setOnAction(event -> viewModel.setLatexDirectory());
        HBox latexDirectoryBox = new HBox(10, latexDirectoryText, latexDirectoryPath, latexDirectoryButton);
        latexDirectoryBox.setAlignment(Pos.CENTER);
        return latexDirectoryBox;
    }

    private VBox getCitationsPane() {
        VBox citationsBox = new VBox(30, citationsDisplay);
        VBox.setVgrow(citationsDisplay, Priority.ALWAYS);
        citationsBox.getStyleClass().add("padding-0");
        return citationsBox;
    }

    private VBox getNotFoundPane() {
        Label titleLabel = new Label(Localization.lang("No citations found"));
        titleLabel.getStyleClass().add("heading");

        Text notFoundText = new Text(Localization.lang("No LaTeX files containing this entry were found."));
        notFoundText.getStyleClass().add("description");

        VBox notFoundBox = new VBox(30, titleLabel, notFoundText);
        notFoundBox.getStyleClass().add("latex-citations-message-box");
        return notFoundBox;
    }

    private VBox getErrorPane() {
        Label titleLabel = new Label(Localization.lang("Error"));
        titleLabel.getStyleClass().add("latex-citations-error-label");
        Text errorMessageText = new Text();
        errorMessageText.textProperty().bind(viewModel.searchErrorProperty());
        VBox errorMessageBox = new VBox(30, titleLabel, errorMessageText);
        errorMessageBox.getStyleClass().add("latex-citations-message-box");
        return errorMessageBox;
    }

    @Override
    protected void bindToEntry(BibEntry entry) {
        if (stateManager.activeTabProperty().get().isPresent()) {
            LibraryTab libraryTab = stateManager.activeTabProperty().get().get();
            viewModel.bindToEntry(libraryTab, entry);
        }
    }
}
