package kalang.tool;

import java.io.File;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Collection;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
import kalang.ast.ClassNode;
import kalang.AstNotFoundException;
import kalang.java.MemoryCompiler;
import kalang.java.MemoryFileManager;
import kalang.util.ClassNameUtil;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.FilenameUtils;

/**
 *
 * @author Kason Yang <im@kasonyang.com>
 */
public class JointFileSystemCompiler extends FileSystemCompiler{
    
    final Map<String,File> javaFiles = new HashMap<>();
    

    @Override
    public void addSourceDir(File sourceDir) throws IOException {
        Collection<File> files = FileUtils.listFiles(sourceDir, new String[]{"java"}, true);
        if(files!=null){
            for(File f:files){
                addSource(sourceDir, f);
            }
        }
        super.addSourceDir(sourceDir);
    }

    @Override
    public void addSource(File srcDir, File file) throws IOException {
        if(file.getName().endsWith(".java")){
            String className = ClassNameUtil.getClassName(srcDir, file);
            javaFiles.put(className,file);
        }else{
            super.addSource(srcDir, file);
        }
    }
    
    private ClassNode createMockClass(String className){
        ClassNode node = new ClassNode();
        node.name = className;
        return node;
    }

    @Override
    protected ClassNode findAst(String className) throws AstNotFoundException {
        try{
            return super.findAst(className);
        }catch(AstNotFoundException ex){
            if(javaFiles.containsKey(className)){
                return createMockClass(className);
            }
            throw ex;
        }
    }
    
    

    @Override
    public void compile() {
        MemoryOutputManager om = new MemoryOutputManager();
        generateJavaStub(om);
        MemoryCompiler javaCompiler = new MemoryCompiler();
        for(File f:javaFiles.values()){
            javaCompiler.addSourceFromFile(f);
        }
        String[] stubNames = om.getClassNames();
        for(String n:stubNames){
            String code = new String(om.getBytes(n));
            javaCompiler.addSourceFromString(n, code);
        }
        if(!javaCompiler.compile()){
            javaCompiler.printDiagnostic();
            return;
        }
        Map<String, byte[]> bytes = javaCompiler.getFileManager().getBytes();
        OutputManager outManager = getOutputManager();
        if(bytes!=null && outManager!=null){
            for(Map.Entry<String, byte[]> e:bytes.entrySet()){
                OutputStream os;
                try {
                    os = outManager.createOutputStream(e.getKey());
                    os.write(e.getValue());
                    os.close();
                } catch (IOException ex) {
                    //TODO handle ex
                    throw new RuntimeException(ex);
                }
            }
        }
        classLoader.addClassLoader(javaCompiler);
        super.compile();
    }
    
    

}

@@ -283,24 +283,130 @@
 ing.Logger;%0A
+import javax.tools.Diagnostic;%0Aimport javax.tools.DiagnosticCollector;%0Aimport javax.tools.JavaFileObject;%0A
 import kalan
@@ -2558,25 +2558,150 @@
     
-javaCompiler.prin
+DiagnosticCollector%3CJavaFileObject%3E dc = javaCompiler.getDiagnosticCollector();%0A            for(Diagnostic%3C? extends JavaFileObject%3E d : dc.ge
 tDia
@@ -2707,19 +2707,76 @@
 agnostic
+s
 ()
-;
+)%7B%0A                handleJavaDiagnostic(d);%0A            %7D
 %0A       
@@ -3488,24 +3488,161 @@
 ile();%0A    %7D
+%0A%0A    protected void handleJavaDiagnostic(Diagnostic%3C? extends JavaFileObject%3E d) %7B%0A        System.err.println(d.getMessage(null));%0A    %7D
 %0A    %0A    %0A%0A

add method