import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.util.HashSet;

import com.redhat.ceylon.cmr.api.RepositoryManager;
import com.redhat.ceylon.cmr.ceylon.CeylonUtils;
import com.redhat.ceylon.compiler.Options;
import com.redhat.ceylon.compiler.js.JsCompiler;
import com.redhat.ceylon.compiler.loader.JsModuleManagerFactory;
import com.redhat.ceylon.compiler.typechecker.TypeChecker;
import com.redhat.ceylon.compiler.typechecker.TypeCheckerBuilder;
import com.redhat.ceylon.compiler.typechecker.context.PhasedUnit;
import com.redhat.ceylon.compiler.typechecker.model.Module;

/**
 * Some hack before a proper unit test harness is put in place
 *
 * @author Emmanuel Bernard <emmanuel@hibernate.org>
 */
public class MainForJsTest {
    
    public static void main(String[] args) throws Exception {
        final Options opts = new Options().addRepo("build/runtime").outDir("build/test/opt_modules");
        final RepositoryManager repoman = CeylonUtils.repoManager()
                .cwd(opts.getCwd())
                .systemRepo(opts.getSystemRepo())
                .userRepos(opts.getRepos())
                .outRepo(opts.getOutDir())
                .buildManager();
        System.out.println("Typechecking Ceylon test code...");
        TypeCheckerBuilder tcb = new TypeCheckerBuilder().verbose(false)
            .moduleManagerFactory(new JsModuleManagerFactory((String)null))
            .usageWarnings(false);
        for (String dir : args) {
            tcb.addSrcDirectory(new File(dir));
        }
        tcb.setRepositoryManager(repoman);
        TypeChecker typeChecker = tcb.getTypeChecker();
        typeChecker.process();
        if (typeChecker.getErrors() > 0) {
            System.exit(1);
        }
        System.out.println("Compiling in prototype style");
        JsCompiler jsc = new JsCompiler(typeChecker, opts).stopOnErrors(true);
        if (jsc.generate()) {
            validateOutput(typeChecker, opts);
        } else {
            jsc.printErrorsAndCount(System.out);
            System.out.println("Skipping output validation.");
        }
        System.out.println("Compiling in lexical scope style");
        jsc = new JsCompiler(typeChecker, opts.optimize(false).outDir("build/test/modules")).stopOnErrors(false);
        if (jsc.generate()) {
            validateOutput(typeChecker, opts);
        } else {
            jsc.printErrors(System.out);
            System.out.println("Skipping output validation.");
        }
    }

    static void validateOutput(TypeChecker typeChecker, Options opts)
            throws FileNotFoundException, IOException {
        int count=0;
        HashSet<Module> tested = new HashSet<Module>();
        for (PhasedUnit pu: typeChecker.getPhasedUnits().getPhasedUnits()) {
            Module mod = pu.getPackage().getModule();
            if (!tested.contains(mod)) {
                File generated = new File(String.format("%s/%s",
                        opts.getOutDir(), toOutputPath(mod)));
                File test = new File(String.format("src/test/ceylon/%s", toTestPath(mod, opts.isOptimize())));
                if (test.exists()) {
                    BufferedReader reader = new BufferedReader(new FileReader(test));
                    BufferedReader outputReader = new BufferedReader(new FileReader(generated));
                    try {
                        int i=0;
                        while (reader.ready() && outputReader.ready()) {
                            i++;
                            String actual = outputReader.readLine();
                            String expected = reader.readLine();
                            if (!expected.equals(actual) && !expected.trim().startsWith("//")) {
                                System.err.printf("error at %s: %d%n", test.getPath(), i); 
                                System.err.println("expected: " + expected);
                                System.err.println("  actual: " + actual);
                                break;
                            }
                        }
                        count++;
                    } finally {
                        reader.close();
                        outputReader.close();
                    }
                }
                tested.add(mod);
            }
        }
        System.out.printf("Ran %d tests%n", count);
    }

    private static String toOutputPath(Module mod) {
        String modname = mod.isDefault() ? "default" :
            mod.getNameAsString().replace('.', '/');
        return mod.isDefault() ? "default/default.js" :
            String.format("%1$s/%2$s/%1$s-%2$s.js", modname, mod.getVersion());
    }

    private static String toTestPath(Module mod, boolean opt) {
        String modname = mod.isDefault() ? "default" :
            mod.getNameAsString().replace('.', '/');
        return String.format("%1$s/%1$s%2$s.js", modname, opt? ".jsopt" : "");
    }
}

@@ -12,162 +12,12 @@
 .io.
-BufferedReader;%0Aimport java.io.File;%0Aimport java.io.FileNotFoundException;%0Aimport java.io.FileReader;%0Aimport java.io.IOException;%0Aimport java.util.HashSet
+File
 ;%0A%0Ai
@@ -401,134 +401,8 @@
 der;
-%0Aimport com.redhat.ceylon.compiler.typechecker.context.PhasedUnit;%0Aimport com.redhat.ceylon.compiler.typechecker.model.Module;
 %0A%0A/*
@@ -1200,16 +1200,8 @@
 ory(
-(String)
 null
@@ -1684,32 +1684,33 @@
 e);%0A        if (
+!
 jsc.generate()) 
@@ -1727,169 +1727,42 @@
     
-validateOutput(typeChecker, opts);%0A        %7D else %7B%0A            jsc.printErrorsAndCount(System.out);%0A            System.out.println(%22Skipping output validation.%22
+jsc.printErrorsAndCount(System.out
 );%0A 
@@ -1960,16 +1960,17 @@
     if (
+!
 jsc.gene
@@ -1995,2616 +1995,52 @@
     
-validateOutput(typeChecker, opts);%0A        %7D else %7B%0A            jsc.printErrors(System.out);%0A            System.out.println(%22Skipping output validation.%22);%0A        %7D%0A    %7D%0A%0A    static void validateOutput(TypeChecker typeChecker, Options opts)%0A            throws FileNotFoundException, IOException %7B%0A        int count=0;%0A        HashSet%3CModule%3E tested = new HashSet%3CModule%3E();%0A        for (PhasedUnit pu: typeChecker.getPhasedUnits().getPhasedUnits()) %7B%0A            Module mod = pu.getPackage().getModule();%0A            if (!tested.contains(mod)) %7B%0A                File generated = new File(String.format(%22%25s/%25s%22,%0A                        opts.getOutDir(), toOutputPath(mod)));%0A                File test = new File(String.format(%22src/test/ceylon/%25s%22, toTestPath(mod, opts.isOptimize())));%0A                if (test.exists()) %7B%0A                    BufferedReader reader = new BufferedReader(new FileReader(test));%0A                    BufferedReader outputReader = new BufferedReader(new FileReader(generated));%0A                    try %7B%0A                        int i=0;%0A                        while (reader.ready() && outputReader.ready()) %7B%0A                            i++;%0A                            String actual = outputReader.readLine();%0A                            String expected = reader.readLine();%0A                            if (!expected.equals(actual) && !expected.trim().startsWith(%22//%22)) %7B%0A                                System.err.printf(%22error at %25s: %25d%25n%22, test.getPath(), i); %0A                                System.err.println(%22expected: %22 + expected);%0A                                System.err.println(%22  actual: %22 + actual);%0A                                break;%0A                            %7D%0A                        %7D%0A                        count++;%0A                    %7D finally %7B%0A                        reader.close();%0A                        outputReader.close();%0A                    %7D%0A                %7D%0A                tested.add(mod);%0A            %7D%0A        %7D%0A        System.out.printf(%22Ran %25d tests%25n%22, count);%0A    %7D%0A%0A    private static String toOutputPath(Module mod) %7B%0A        String modname = mod.isDefault() ? %22default%22 :%0A            mod.getNameAsString().replace('.', '/');%0A        return mod.isDefault() ? %22default/default.js%22 :%0A            String.format(%22%251$s/%252$s/%251$s-%252$s.js%22, modname, mod.getVersion());%0A    %7D%0A%0A    private static String toTestPath(Module mod, boolean opt) %7B%0A        String modname = mod.isDefault() ? %22default%22 :%0A            mod.getNameAsString().replace('.', '/');%0A        return String.format(%22%251$s/%251$s%252$s.js%22, modname, opt? %22.jsopt%22 : %22%22);%0A    %7D
+jsc.printErrors(System.out);%0A        %7D%0A    %7D%0A
 %0A%7D%0A

remove the generated js comparison, it's useless