package org.dita.dost.util;

import static org.dita.dost.util.Constants.ANT_TEMP_DIR;
import static org.dita.dost.util.URLUtils.*;

import org.apache.tools.ant.Project;
import org.apache.tools.ant.types.AbstractFileSet;
import org.apache.tools.ant.types.Resource;
import org.apache.tools.ant.types.ResourceCollection;
import org.apache.tools.ant.types.resources.FileResource;
import org.apache.tools.ant.types.resources.URLResource;
import org.dita.dost.invoker.ExtensibleAntInvoker;

import java.io.File;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;

import static org.dita.dost.util.Constants.ANT_REFERENCE_JOB;

/**
 * Resource collection that finds matching resources from job configuration.
 */
public class JobSourceSet extends AbstractFileSet implements ResourceCollection {

    private String format;
    private Boolean hasConref;
    private Boolean isResourceOnly;
    private Collection<Resource> res;
    private boolean isFilesystemOnly = true;

    public JobSourceSet() {
        super();
    }

    private Collection<Resource> getResults() {
        if (res == null) {
            final Job job = getJob();
            res = new ArrayList<>();
            for (final Job.FileInfo f : job.getFileInfo(new Job.FileInfo.Filter<Job.FileInfo>() {
                @Override
                public boolean accept(final Job.FileInfo f) {
                    return (format == null || format.equals(f.format)) &&
                            (hasConref == null || f.hasConref == hasConref) &&
                            (isResourceOnly == null || f.isResourceOnly == isResourceOnly);
                }
            })) {
                log("Scanning for " + f.file.getPath(), Project.MSG_VERBOSE);
                final File tempFile = new File(job.tempDir, f.file.getPath());
                if (tempFile.exists()) {
                    log("Found temporary directory file " + tempFile, Project.MSG_VERBOSE);
                    res.add(new FileResource(job.tempDir, f.file.toString()));
                } else if (f.src.getScheme().equals("file")) {
                    final File srcFile = new File(f.src);
                    if (srcFile.exists()) {
                        log("Found source directory file " + srcFile, Project.MSG_VERBOSE);
                        res.add(new FileResource(toFile(job.getInputDir()), f.file.toString()));
                    } else {
                        log("File " + f.src + " not found", Project.MSG_ERR);
                    }
                } else if (f.src.getScheme().equals("data")) {
                    log("Ignore data URI", Project.MSG_VERBOSE);
                } else {
                    log("Found source URI " + f.src.toString(), Project.MSG_VERBOSE);
                    try {
                        final JobResource r = new JobResource(job.getInputDir().toURL(), f.uri.toString());
                        res.add(r);
                    } catch (final MalformedURLException e) {
                        throw new IllegalArgumentException(e);
                    }
                    isFilesystemOnly = false;
                }
            }
        }
        return res;
    }

    private Job getJob() {
        String tempDir = getProject().getUserProperty(ANT_TEMP_DIR);
        if (tempDir == null) {
            tempDir = getProject().getProperty(ANT_TEMP_DIR);
        }
        if (tempDir == null) {
            throw new IllegalStateException();
        }
        final Job job = ExtensibleAntInvoker.getJob(new File(tempDir), getProject());
        if (job == null) {
            throw new IllegalStateException();
        }
        return job;
    }

    @Override
    public Iterator<Resource> iterator() {
        return getResults().iterator();
    }

    @Override
    public int size() {
        return getResults().size();
    }

    @Override
    public boolean isFilesystemOnly() {
        getResults();
        return isFilesystemOnly;
    }

    public void setFormat(final String format) {
        this.format = format;
    }

    public void setConref(final boolean conref) {
        this.hasConref = conref;
    }

    public void setProcessingRole(final String processingRole) {
        this.isResourceOnly = processingRole.equals(Constants.ATTR_PROCESSING_ROLE_VALUE_RESOURCE_ONLY);
    }

    private static class JobResource extends URLResource {
        private final String relPath;
        public JobResource(final URL baseURL, final String relPath) {
            super();
            setBaseURL(baseURL);
            setRelativePath(relPath);
            this.relPath = relPath;
        }
        /**
         * Get the name of this URLResource with original relative path.
         *
         * URLResource will return full URL file part that also contains ancestor directories.
         **/
        @Override
        public synchronized String getName() {
            if (isReference()) {
                return ((Resource) getCheckedRef()).getName();
            }
            return relPath;
        }
    }

}

@@ -648,71 +648,8 @@
 r;%0A%0A
-import static org.dita.dost.util.Constants.ANT_REFERENCE_JOB;%0A%0A
 /**%0A
@@ -2277,32 +2277,157 @@
 t.MSG_VERBOSE);%0A
+                        final File rel = FileUtils.getRelativePath(new File(new File(job.getInputDir()), %22dummy%22), srcFile);%0A
                 
@@ -2486,31 +2486,27 @@
 Dir()), 
-f.file.toString
+rel.getPath
 ()));%0A  

Fix relative path when copy source is in src directory