package p.studio.lsp.services.protocol;

import org.eclipse.lsp4j.*;
import org.eclipse.lsp4j.services.LanguageClient;
import org.eclipse.lsp4j.services.TextDocumentService;
import p.studio.lsp.messages.LspProjectContext;
import p.studio.lsp.services.LanguageServiceBridge;
import p.studio.lsp.services.protocol.mapping.ProtocolMessageMapper;

import java.util.Objects;
import java.util.concurrent.CompletableFuture;

public final class PrometeuTextDocumentService implements TextDocumentService {
    private final LspProjectContext project;
    private final LanguageServiceBridge languageServiceBridge;
    private final ProtocolMessageMapper protocolMessageMapper;
    private volatile LanguageClient client;

    public PrometeuTextDocumentService(
            final LspProjectContext project,
            final LanguageServiceBridge languageServiceBridge,
            final ProtocolMessageMapper protocolMessageMapper) {
        this.project = Objects.requireNonNull(project, "project");
        this.languageServiceBridge = Objects.requireNonNull(languageServiceBridge, "languageServiceBridge");
        this.protocolMessageMapper = Objects.requireNonNull(protocolMessageMapper, "protocolMessageMapper");
    }

    void connect(final LanguageClient client) {
        this.client = client;
    }

    @Override
    public void didOpen(final DidOpenTextDocumentParams params) {
        publishAnalysis(params.getTextDocument().getUri(), params.getTextDocument().getText());
    }

    @Override
    public void didChange(final DidChangeTextDocumentParams params) {
        final String text = params.getContentChanges().isEmpty()
                ? ""
                : params.getContentChanges().getFirst().getText();
        publishAnalysis(params.getTextDocument().getUri(), text);
    }

    @Override
    public void didClose(final DidCloseTextDocumentParams params) {
        final LanguageClient currentClient = client;
        if (currentClient == null) {
            return;
        }
        currentClient.publishDiagnostics(protocolMessageMapper.emptyDiagnostics(params.getTextDocument().getUri()));
    }

    @Override
    public void didSave(final DidSaveTextDocumentParams params) {
        final LanguageClient currentClient = client;
        if (currentClient == null) {
            return;
        }
        currentClient.logMessage(protocolMessageMapper.mapInfoMessage(
                languageServiceBridge.onSave(project, params.getTextDocument().getUri())));
    }

    @Override
    public CompletableFuture<Hover> hover(final HoverParams params) {
        return CompletableFuture.completedFuture(protocolMessageMapper.mapHover(languageServiceBridge.hover(
                project,
                params.getTextDocument().getUri(),
                params.getPosition().getLine(),
                params.getPosition().getCharacter())));
    }

    private void publishAnalysis(
            final String uri,
            final String text) {
        final LanguageClient currentClient = client;
        if (currentClient == null) {
            return;
        }
        currentClient.publishDiagnostics(protocolMessageMapper.mapDiagnostics(
                uri,
                languageServiceBridge.analyzeDocument(project, uri, text)));
    }
}
