/*
 * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
 */

package com.sun.glass.test;

import com.sun.glass.ui.*;

import java.io.*;
import java.util.*;
import java.net.*;

import org.junit.runner.*;
import org.junit.runner.notification.*;

public class Main
{
    public static void main(String args[])
    {
        start(args);
    }

    static class TestLaunchable implements Launchable
    {
        public void finishLaunching(String[] args)
        {
            // there is no Thread context class loader here yet, why not?
            //runTests();
        }
    }

    protected static void start(String args[])
    {
        try
        {
            String title = "Main";
            int fps = 30;
            TestLaunchable launchable = new TestLaunchable();
            Application.Run(args, title, launchable);

            // important!
            Application.GetApplication().setTerminateWhenLastWindowClosed(false);

            runTests();
        }
        catch (Throwable t)
        {
            t.printStackTrace();
        }
    }

    private static void runTests()
    {
        JUnitCore core = new JUnitCore();
        String exclude = Main.getMainClassName();
        String packageName = exclude.substring(0, exclude.lastIndexOf("."));
        Class candidates[] = null;
        try
        {
            candidates = getClasses(packageName);
        }
        catch (ClassNotFoundException ex)
        {
            ex.printStackTrace();
        }
        catch (IOException ex)
        {
            ex.printStackTrace();
        }
        
        System.out.println("\n\n"+packageName+" tests:");
        for (int i=0; i<candidates.length; i++)
        {
            Class candidate = candidates[i];
            if (candidate.isMemberClass() == false)
            {
                String name = candidate.getCanonicalName();
                if ((name != null) && (exclude.equals(name) == false))
                {
                    System.out.println("\n\n--------------------------------------------------------------------");
                    System.out.println(name+"\n");
                    Result result = core.run(candidate);
                    if (result.wasSuccessful() == true)
                    {
                        System.out.println("SUCCESS\n");
                    }
                    else
                    {
                        System.out.println("FAILURE!\n");
                    }

                    long millis = result.getRunTime();
                    float time = (float)millis / 1000.0f;
                    System.out.println("    time:   "+time+" [sec]");
                    //System.out.println("    ran:    "+result.getRunCount()+" [tests]");
                    System.out.println("    passed: "+(result.getRunCount()-result.getFailureCount())+" [tests]");
                    if (result.getFailureCount() > 0)
                    {
                        System.out.println("    failed: "+result.getFailureCount()+" [tests]");
                    }

                    for (Failure f: result.getFailures())
                    {
                        System.out.println("\n------------");
                        System.out.println("    failure:   "+f.getTestHeader()+"\n");
                        System.out.println(f.getTrace());
                    }
                }
            }
        }

        System.out.println("\n\n");
        System.exit(0);
    }

    // http://stackoverflow.com/questions/41894/0-program-name-in-java-discover-main-class
    private static String getMainClassName()
    {
        StackTraceElement stack[] = Thread.currentThread().getStackTrace();
        StackTraceElement main = stack[stack.length - 1];
        return  main.getClassName();
    }

    // http://snippets.dzone.com/posts/show/4831
    private static Class[] getClasses(String packageName) throws ClassNotFoundException, IOException
    {
        ClassLoader classLoader = Thread.currentThread().getContextClassLoader();

        String path = packageName.replace('.', '/');
        Enumeration<URL> resources = classLoader.getResources(path);
        List<File> dirs = new ArrayList<File>();
        while (resources.hasMoreElements())
        {
            URL resource = resources.nextElement();
            dirs.add(new File(resource.getFile()));
        }

        ArrayList<Class> classes = new ArrayList<Class>();
        for (File directory : dirs)
        {
            classes.addAll(findClasses(directory, packageName));
        }

        return classes.toArray(new Class[classes.size()]);
    }

    private static List<Class> findClasses(File directory, String packageName) throws ClassNotFoundException
    {
        List<Class> classes = new ArrayList<Class>();
        if (!directory.exists())
        {
            return classes;
        }

        File[] files = directory.listFiles();
        for (File file : files)
        {
            if (file.isDirectory())
            {
                classes.addAll(findClasses(file, packageName + "." + file.getName()));
            }
            else if (file.getName().endsWith(".class"))
            {
                classes.add(Class.forName(packageName + '.' + file.getName().substring(0, file.getName().length() - 6)));
            }
        }
        return classes;
    }
}
