package org.jboss.resteasy.utils;


import javax.ws.rs.ApplicationPath;
import javax.ws.rs.core.Application;
import javax.ws.rs.ext.Provider;
import java.io.InputStream;
import java.util.HashSet;
import java.util.Set;

/**
 * Base class used from deployment.
 */
@Provider
@ApplicationPath("/")
public class TestApplication extends Application {

    public static Set<Class<?>> classes = new HashSet<Class<?>>();
    public static Set<Object> singletons = new HashSet<Object>();

    /**
     * Load resources from classes.txt file from deployment
     *
     * @return Array of class names.
     */
    public static String[] getClassesFromDeployment(String name) {
        String resource = name + ".txt";
        String stripped = resource.startsWith("/") ?
                resource.substring(1) : resource;

        InputStream stream = null;
        ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
        if (classLoader != null) {
            stream = classLoader.getResourceAsStream(stripped);
        }
        if (stream == null) {
            stream = TestApplication.class.getResourceAsStream(resource);
        }
        if (stream == null) {
            stream = TestApplication.class.getClassLoader().getResourceAsStream(stripped);
        }
        if (stream == null) {
            return new String[0];
        }
        return convertStreamToString(stream).split(",");
    }

    /**
     * Convert input stream to String
     *
     * @param is Input stream
     * @return string
     */
    private static String convertStreamToString(final java.io.InputStream is) {
        java.util.Scanner s = new java.util.Scanner(is).useDelimiter("\\A");
        return s.hasNext() ? s.next() : "";
    }

    /**
     * @see javax.ws.rs.core.Application#getClasses()
     */
    @Override
    public Set<Class<?>> getClasses() {
        if (classes.isEmpty()) {
            for (String clazz : getClassesFromDeployment("classes")) {
                if (!clazz.isEmpty()) {
                    try {
                        classes.add(Class.forName(clazz));
                    } catch (ClassNotFoundException e) {
                        throw new RuntimeException("Class " + clazz + " not found.", e);
                    }
                }
            }
        }
        return classes;
    }

    /**
     * @see javax.ws.rs.core.Application#getSingletons()
     */
    @Override
    public Set<Object> getSingletons() {
        if (singletons.isEmpty()) {
            for (String clazz : getClassesFromDeployment("singletons")) {
                if (!clazz.isEmpty()) {
                    try {
                        singletons.add(Class.forName(clazz).newInstance());
                    } catch (Exception e) {
                        throw new RuntimeException("Class " + clazz + " not found.", e);
                    }
                }
            }
        }
        return singletons;
    }
}
