package org.metaborg.spoofax.core.tracing;

import java.io.File;

import javax.annotation.Nullable;

import org.apache.commons.vfs2.FileObject;
import org.metaborg.core.MetaborgException;
import org.metaborg.core.resource.IResourceService;
import org.metaborg.core.source.ISourceLocation;
import org.metaborg.core.source.ISourceRegion;
import org.metaborg.spoofax.core.stratego.IStrategoCommon;
import org.metaborg.util.log.ILogger;
import org.metaborg.util.log.LoggerUtils;
import org.spoofax.interpreter.terms.IStrategoString;
import org.spoofax.interpreter.terms.IStrategoTerm;
import org.spoofax.interpreter.terms.ITermFactory;
import org.strategoxt.HybridInterpreter;

import com.google.inject.Inject;

public class TracingCommon {
    /**
     * Data class representing a term with its corresponding region in the source text.
     */
    public static class TermWithRegion {
        public final IStrategoTerm term;
        public final ISourceRegion region;


        public TermWithRegion(IStrategoTerm term, ISourceRegion region) {
            this.term = term;
            this.region = region;
        }
    }


    private static final ILogger logger = LoggerUtils.logger(TracingCommon.class);

    private final IResourceService resourceService;
    private final ISpoofaxTracingService tracingService;

    private final IStrategoCommon common;


    @Inject public TracingCommon(IResourceService resourceService, ISpoofaxTracingService tracingService,
        IStrategoCommon common) {
        this.resourceService = resourceService;
        this.tracingService = tracingService;
        this.common = common;
    }


    public TermWithRegion outputs(ITermFactory termFactory, HybridInterpreter runtime, FileObject location,
        FileObject resource, IStrategoTerm result, Iterable<IStrategoTerm> inRegion, String strategy)
        throws MetaborgException {
        final File localContextLocation = resourceService.localFile(location);
        final File localResource = resourceService.localPath(resource);
        if(localContextLocation == null || localResource == null) {
            return null;
        }
        final IStrategoString path = common.localResourceTerm(localResource, localContextLocation);
        final IStrategoString contextPath = common.localLocationTerm(localContextLocation);

        for(IStrategoTerm term : inRegion) {
            final IStrategoTerm inputTerm =
                termFactory.makeTuple(term, termFactory.makeTuple(), result, path, contextPath);
            final IStrategoTerm output = common.invoke(runtime, inputTerm, strategy);
            if(output == null) {
                continue;
            }

            final ISourceLocation highlightLocation = tracingService.location(term);
            if(highlightLocation == null) {
                logger.debug("Cannot get source region for {}", term);
                continue;
            }

            return new TermWithRegion(output, highlightLocation.region());
        }

        return null;
    }

    public @Nullable ISourceLocation getTargetLocation(IStrategoTerm term) {
        final ISourceLocation targetLocation = tracingService.location(term);
        if(targetLocation == null || targetLocation.resource() == null) {
            return null;
        }
        return targetLocation;
    }
}

@@ -41,30 +41,8 @@
 g;%0A%0A
-import java.io.File;%0A%0A
 impo
@@ -163,60 +163,8 @@
 on;%0A
-import org.metaborg.core.resource.IResourceService;%0A
 impo
@@ -398,62 +398,8 @@
 ls;%0A
-import org.spoofax.interpreter.terms.IStrategoString;%0A
 impo
@@ -1077,60 +1077,8 @@
 );%0A%0A
-    private final IResourceService resourceService;%0A
     
@@ -1212,42 +1212,8 @@
 mon(
-IResourceService resourceService, 
 ISpo
@@ -1246,24 +1246,16 @@
 Service,
-%0A       
  IStrate
@@ -1277,56 +1277,8 @@
 ) %7B%0A
-        this.resourceService = resourceService;%0A
     
@@ -1606,638 +1606,146 @@
 n %7B%0A
-        final File localContextLocation = resourceService.localFile(location);%0A        final File localResource = resourceService.localPath(resource);%0A        if(localContextLocation == null %7C%7C localResource == null) %7B%0A            return null;%0A        %7D%0A        final IStrategoString path = common.localResourceTerm(localResource, localContextLocation);%0A        final IStrategoString contextPath = common.localLocationTerm(localContextLocation);%0A%0A        for(IStrategoTerm term : inRegion) %7B%0A            final IStrategoTerm inputTerm =%0A                termFactory.makeTuple(term, termFactory.makeTuple(), result, path, contextPath
+%0A        for(IStrategoTerm term : inRegion) %7B%0A            final IStrategoTerm inputTerm = common.builderInputTerm(term, resource, location
 );%0A 

Fix tuple passed to editor-hover (fixes http://yellowgrass.org/issue/SpoofaxWithCore/165).