package p.studio.workspaces.editor;

import javafx.geometry.Pos;
import javafx.scene.Node;
import javafx.scene.control.Label;
import javafx.scene.layout.HBox;
import javafx.scene.layout.Priority;
import javafx.scene.layout.Region;
import p.studio.Container;
import p.studio.projects.ProjectReference;
import p.studio.utilities.i18n.I18n;

import java.nio.file.Path;
import java.util.Optional;

public final class EditorStatusBar extends HBox {
    private final HBox breadcrumb = new HBox(6);
    private final Label position = new Label();
    private final Label lineSeparator = new Label();
    private final Label indentation = new Label();
    private final Label language = new Label();
    private final Label readOnly = new Label();

    public EditorStatusBar() {
        setAlignment(Pos.CENTER_LEFT);
        setSpacing(8);
        getStyleClass().add("editor-workspace-status-bar");

        breadcrumb.getStyleClass().add("editor-workspace-status-breadcrumb");
        breadcrumb.setAlignment(Pos.CENTER_LEFT);

        final var spacer = new Region();
        HBox.setHgrow(spacer, Priority.ALWAYS);

        styleChip(position);
        position.getStyleClass().add("editor-workspace-status-chip-position");
        styleChip(lineSeparator);
        lineSeparator.getStyleClass().add("editor-workspace-status-chip-line-separator");
        styleChip(indentation);
        indentation.getStyleClass().add("editor-workspace-status-chip-indentation");
        styleChip(language);
        language.getStyleClass().add("editor-workspace-status-chip-language");
        styleChip(readOnly);
        readOnly.getStyleClass().add("editor-workspace-status-chip-read-only");

        getChildren().addAll(
                breadcrumb,
                spacer,
                position,
                lineSeparator,
                indentation,
                language,
                readOnly
        );

        showPlaceholder();
    }

    public void showFile(final ProjectReference projectReference, final EditorOpenFileBuffer fileBuffer) {
        showBreadcrumb(projectReference, fileBuffer.path());
        bindDefault(position, I18n.CODE_EDITOR_STATUS_POSITION);
        setText(lineSeparator, fileBuffer.lineSeparator());
        bindDefault(indentation, I18n.CODE_EDITOR_STATUS_INDENTATION);
        setText(language, extensionText(fileBuffer.path()));
        bindDefault(readOnly, I18n.CODE_EDITOR_STATUS_READ_ONLY);
    }

    public void showPlaceholder() {
        breadcrumb.getChildren().setAll(placeholderLabel());
        bindDefault(position, I18n.CODE_EDITOR_STATUS_POSITION);
        bindDefault(lineSeparator, I18n.CODE_EDITOR_STATUS_LINE_SEPARATOR);
        bindDefault(indentation, I18n.CODE_EDITOR_STATUS_INDENTATION);
        bindDefault(language, I18n.CODE_EDITOR_STATUS_LANGUAGE);
        bindDefault(readOnly, I18n.CODE_EDITOR_STATUS_READ_ONLY);
    }

    private void bindDefault(final Label label, final I18n key) {
        bindText(label, key);
    }

    private void bindText(final Label label, final I18n key) {
        label.textProperty().unbind();
        label.textProperty().bind(Container.i18n().bind(key));
    }

    private Label placeholderLabel() {
        final var label = new Label();
        label.textProperty().bind(Container.i18n().bind(I18n.CODE_EDITOR_STATUS_BREADCRUMB));
        return label;
    }

    private void showBreadcrumb(final ProjectReference projectReference, final Path filePath) {
        breadcrumb.getChildren().clear();
        breadcrumb.getChildren().add(segment(
                rootLabel(projectReference),
                EditorWorkspaceIcons.folderDefault(),
                true));

        final var relativePath = projectReference.rootPath()
                .toAbsolutePath()
                .normalize()
                .relativize(filePath.toAbsolutePath().normalize());

        boolean insideSourceTree = false;
        Path accumulated = projectReference.rootPath().toAbsolutePath().normalize();
        for (int index = 0; index < relativePath.getNameCount(); index++) {
            final var part = relativePath.getName(index).toString();
            accumulated = accumulated.resolve(part);
            final boolean isLast = index == relativePath.getNameCount() - 1;
            if ("src".equals(part)) {
                insideSourceTree = true;
            }
            breadcrumb.getChildren().add(separator());
            breadcrumb.getChildren().add(segment(
                    part,
                    iconForSegment(part, isLast, insideSourceTree),
                    false));
        }
    }

    private String rootLabel(final ProjectReference projectReference) {
        final var directoryName = Optional.ofNullable(projectReference.rootPath().getFileName())
                .map(Path::toString)
                .filter(name -> !name.isBlank())
                .orElse(projectReference.name());
        return directoryName + " (" + projectReference.name() + ")";
    }

    private HBox segment(final String text, final Node icon, final boolean root) {
        final var label = new Label(text);
        label.getStyleClass().add("editor-workspace-status-breadcrumb-text");

        final var box = new HBox(6, icon, label);
        box.setAlignment(Pos.CENTER_LEFT);
        box.getStyleClass().add("editor-workspace-status-breadcrumb-segment");
        if (root) {
            box.getStyleClass().add("editor-workspace-status-breadcrumb-segment-root");
        }
        return box;
    }

    private Label separator() {
        final var label = new Label(">");
        label.getStyleClass().add("editor-workspace-status-breadcrumb-separator");
        return label;
    }

    private Node iconForSegment(final String name, final boolean isFile, final boolean insideSourceTree) {
        if (isFile) {
            if ("prometeu.json".equals(name)) {
                return EditorWorkspaceIcons.cog();
            }
            return EditorWorkspaceIcons.file();
        }

        if ("build".equals(name) || "cartridge".equals(name)) {
            return EditorWorkspaceIcons.folderBuild();
        }
        if ("src".equals(name) || insideSourceTree) {
            return EditorWorkspaceIcons.folderSource();
        }
        return EditorWorkspaceIcons.folderDefault();
    }

    private void setText(final Label label, final String text) {
        label.textProperty().unbind();
        label.setText(text);
    }

    private void styleChip(final Label label) {
        if (!label.getStyleClass().contains("editor-workspace-status-chip")) {
            label.getStyleClass().add("editor-workspace-status-chip");
        }
    }

    private String extensionText(final java.nio.file.Path path) {
        final var fileName = path.getFileName().toString();
        final var dot = fileName.lastIndexOf('.');
        return dot >= 0 && dot < fileName.length() - 1
                ? fileName.substring(dot + 1)
                : fileName;
    }
}
