package p.studio.workspaces.editor;

import javafx.scene.control.Alert;
import javafx.scene.Node;
import javafx.scene.control.SplitPane;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.Priority;
import javafx.scene.layout.VBox;
import org.fxmisc.richtext.CodeArea;
import org.fxmisc.richtext.LineNumberFactory;
import p.studio.projects.ProjectReference;
import p.studio.utilities.i18n.I18n;
import p.studio.workspaces.Workspace;
import p.studio.workspaces.WorkspaceId;

public final class EditorWorkspace extends Workspace {
    private final BorderPane root = new BorderPane();
    private final CodeArea codeArea = new CodeArea();
    private final EditorProjectNavigatorPanel navigatorPanel = new EditorProjectNavigatorPanel();
    private final EditorOutlinePanel outlinePanel = new EditorOutlinePanel();
    private final EditorHelperPanel helperPanel = new EditorHelperPanel();
    private final EditorStatusBar statusBar = new EditorStatusBar();
    private final EditorTabStrip tabStrip = new EditorTabStrip();
    private final EditorProjectSnapshotService snapshotService = new EditorProjectSnapshotService();
    private final EditorFileBufferLoader fileBufferLoader = new EditorFileBufferLoader();
    private final EditorOpenFileSession openFileSession = new EditorOpenFileSession();

    public EditorWorkspace(final ProjectReference projectReference) {
        super(projectReference);
        root.getStyleClass().add("editor-workspace");
        codeArea.setParagraphGraphicFactory(LineNumberFactory.get(codeArea));
        codeArea.setEditable(false);
        codeArea.setWrapText(false);
        codeArea.getStyleClass().add("editor-workspace-code-area");
        showEditorPlaceholder();
        navigatorPanel.setRefreshAction(this::refreshNavigator);
        navigatorPanel.setFileSelectionAction(this::openNode);
        tabStrip.setTabSelectionAction(path -> {
            openFileSession.activate(path);
            renderSession();
        });

        root.setCenter(buildLayout());
        statusBar.showPlaceholder();
    }

    @Override public WorkspaceId workspaceId() { return WorkspaceId.EDITOR; }
    @Override public I18n title() { return I18n.WORKSPACE_CODE; }
    @Override public Node rootNode() { return root; }

    @Override
    public void load() {
        refreshNavigator();
    }

    @Override
    public void unLoad() {

    }

    public CodeArea codeArea() { return codeArea; }

    private void refreshNavigator() {
        navigatorPanel.setSnapshot(snapshotService.createSnapshot(projectReference));
    }

    private void openNode(final EditorProjectNode node) {
        fileBufferLoader.load(node.path())
                .ifPresentOrElse(this::openFile, () -> showUnsupportedFileModal(node.path()));
    }

    private void openFile(final EditorOpenFileBuffer fileBuffer) {
        openFileSession.open(fileBuffer);
        renderSession();
    }

    private void renderSession() {
        final var activeFile = openFileSession.activeFile();
        tabStrip.showOpenFiles(
                openFileSession.openFiles(),
                activeFile.map(EditorOpenFileBuffer::path).orElse(null));
        if (activeFile.isEmpty()) {
            showEditorPlaceholder();
            statusBar.showPlaceholder();
            return;
        }

        final var fileBuffer = activeFile.orElseThrow();
        codeArea.replaceText(fileBuffer.content());
        statusBar.showFile(projectReference, fileBuffer);
    }

    private void showUnsupportedFileModal(final java.nio.file.Path path) {
        final var alert = new Alert(Alert.AlertType.INFORMATION);
        if (root.getScene() != null) {
            alert.initOwner(root.getScene().getWindow());
        }
        alert.setHeaderText(null);
        alert.setTitle(p.studio.Container.i18n().text(I18n.CODE_EDITOR_UNSUPPORTED_FILE_TITLE));
        alert.setContentText(p.studio.Container.i18n().format(I18n.CODE_EDITOR_UNSUPPORTED_FILE_MESSAGE, path.getFileName()));
        alert.showAndWait();
    }

    private void showEditorPlaceholder() {
        codeArea.replaceText("""
        // Read-only first wave
        // Open a supported text file from the project navigator.
        """);
    }

    private VBox buildLayout() {
        final var content = new SplitPane(buildLeftColumn(), buildCenterColumn());
        content.setDividerPositions(0.30);
        content.getStyleClass().add("editor-workspace-split");

        final var layout = new VBox(12, content, helperPanel, statusBar);
        layout.getStyleClass().add("editor-workspace-layout");
        VBox.setVgrow(content, Priority.ALWAYS);
        return layout;
    }

    private VBox buildLeftColumn() {
        final var leftColumn = new VBox(12, navigatorPanel, outlinePanel);
        leftColumn.getStyleClass().add("editor-workspace-left-column");
        VBox.setVgrow(navigatorPanel, Priority.ALWAYS);
        return leftColumn;
    }

    private VBox buildCenterColumn() {
        final var centerColumn = new VBox(12, tabStrip, codeArea);
        centerColumn.getStyleClass().add("editor-workspace-center-column");
        VBox.setVgrow(codeArea, Priority.ALWAYS);
        return centerColumn;
    }
}
