package org.metaborg.spoofax.eclipse.editor;

import org.apache.commons.vfs2.FileObject;
import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.ITextHover;
import org.eclipse.jface.text.contentassist.ContentAssistant;
import org.eclipse.jface.text.contentassist.IContentAssistant;
import org.eclipse.jface.text.hyperlink.IHyperlinkDetector;
import org.eclipse.jface.text.hyperlink.URLHyperlinkDetector;
import org.eclipse.jface.text.quickassist.IQuickAssistAssistant;
import org.eclipse.jface.text.reconciler.IReconciler;
import org.eclipse.jface.text.source.ISourceViewer;
import org.eclipse.jface.text.source.SourceViewerConfiguration;
import org.eclipse.ui.editors.text.TextSourceViewerConfiguration;
import org.metaborg.spoofax.core.completion.ICompletionService;
import org.metaborg.spoofax.core.language.ILanguage;
import org.metaborg.spoofax.core.processing.analyze.IAnalysisResultRequester;
import org.metaborg.spoofax.core.processing.parse.IParseResultRequester;
import org.metaborg.spoofax.core.syntax.ISyntaxService;
import org.metaborg.spoofax.core.tracing.IHoverService;
import org.metaborg.spoofax.core.tracing.IReferenceResolver;
import org.metaborg.spoofax.eclipse.resource.IEclipseResourceService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.google.common.collect.Iterables;

public class SpoofaxSourceViewerConfiguration<P, A> extends TextSourceViewerConfiguration {
    private static final Logger logger = LoggerFactory.getLogger(SourceViewerConfiguration.class);

    private final IEclipseResourceService resourceService;
    private final ISyntaxService<P> syntaxService;
    private final IParseResultRequester<P> parseResultRequester;
    private final IAnalysisResultRequester<P, A> analysisResultRequester;
    private final IReferenceResolver<P, A> referenceResolver;
    private final IHoverService<P, A> hoverService;
    private final ICompletionService completionService;

    private final SpoofaxEditor editor;


    public SpoofaxSourceViewerConfiguration(IEclipseResourceService resourceService, ISyntaxService<P> syntaxService,
        IParseResultRequester<P> parseResultRequester, IAnalysisResultRequester<P, A> analysisResultRequester,
        IReferenceResolver<P, A> referenceResolver, IHoverService<P, A> hoverService,
        ICompletionService completionService, IPreferenceStore preferenceStore, SpoofaxEditor editor) {
        super(preferenceStore);

        this.resourceService = resourceService;
        this.syntaxService = syntaxService;
        this.parseResultRequester = parseResultRequester;
        this.analysisResultRequester = analysisResultRequester;
        this.referenceResolver = referenceResolver;
        this.hoverService = hoverService;
        this.completionService = completionService;

        this.editor = editor;
    }

    @Override public String[] getDefaultPrefixes(ISourceViewer sourceViewer, String contentType) {
        final ILanguage language = editor.language();
        if(language == null) {
            logger.warn("Identified language for {} is null, toggle comment is disabled until language is identified",
                editor.resource());
            return new String[0];
        }
        return Iterables.toArray(syntaxService.singleLineCommentPrefixes(language), String.class);
    }

    @Override public IContentAssistant getContentAssistant(ISourceViewer sourceViewer) {
        final FileObject resource = editor.resource();
        final ILanguage language = editor.language();
        final IDocument document = editor.document();
        if(language == null) {
            logger.warn("Identified language for {} is null, content assist is disabled until language is identified",
                resource);
            return null;
        }

        final ContentAssistant assistant = new ContentAssistant();
        final SpoofaxContentAssistProcessor processor =
            new SpoofaxContentAssistProcessor(completionService, parseResultRequester, resource, document, language);
        assistant.setContentAssistProcessor(processor, IDocument.DEFAULT_CONTENT_TYPE);
        assistant.setRepeatedInvocationMode(true);
        return assistant;
    }

    @Override public IHyperlinkDetector[] getHyperlinkDetectors(ISourceViewer sourceViewer) {
        final FileObject resource = editor.resource();
        final ILanguage language = editor.language();

        if(language == null) {
            logger.warn(
                "Identified language for {} is null, reference resolution is disabled until language is identified",
                resource);
            return new IHyperlinkDetector[] { new URLHyperlinkDetector() };
        }

        return new IHyperlinkDetector[] {
            new SpoofaxHyperlinkDetector<P, A>(resourceService, analysisResultRequester, referenceResolver, resource,
                editor), new URLHyperlinkDetector() };
    }

    @Override public ITextHover getTextHover(ISourceViewer sourceViewer, String contentType) {
        final FileObject resource = editor.resource();
        final ILanguage language = editor.language();

        if(language == null) {
            logger.warn("Identified language for {} is null, hover tooltips are disabled until language is identified",
                resource);
            return null;
        }

        return new SpoofaxTextHover<P, A>(analysisResultRequester, hoverService, resource);
    }

    @Override public IReconciler getReconciler(ISourceViewer sourceViewer) {
        // Return null to disable TextSourceViewerConfiguration reconciler which does spell checking.
        return null;
    }

    @Override public IQuickAssistAssistant getQuickAssistAssistant(ISourceViewer sourceViewer) {
        // Return null to disable TextSourceViewerConfiguration quick assist which does spell checking.
        return null;
    }
}

@@ -111,76 +111,305 @@
 ace.
-preference.IPreferenceStore;%0Aimport org.eclipse.jface.text.IDocument
+internal.text.html.HTMLTextPresenter;%0Aimport org.eclipse.jface.preference.IPreferenceStore;%0Aimport org.eclipse.jface.text.DefaultInformationControl;%0Aimport org.eclipse.jface.text.IDocument;%0Aimport org.eclipse.jface.text.IInformationControl;%0Aimport org.eclipse.jface.text.IInformationControlCreator
 ;%0Aim
@@ -922,32 +922,70 @@
 rConfiguration;%0A
+import org.eclipse.swt.widgets.Shell;%0A
 import org.eclip
@@ -1648,16 +1648,49 @@
 ables;%0A%0A
+@SuppressWarnings(%22restriction%22)%0A
 public c
@@ -5775,32 +5775,382 @@
 source);%0A    %7D%0A%0A
+    public IInformationControlCreator getInformationControlCreator(ISourceViewer sourceViewer) %7B%0A        return new IInformationControlCreator() %7B%0A            public IInformationControl createInformationControl(Shell parent) %7B%0A                return new DefaultInformationControl(parent, new HTMLTextPresenter(true));%0A            %7D%0A        %7D;%0A    %7D%0A%0A
     @Override pu

Allow HTML in hover tooltips.