/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  The ASF licenses this file to You
 * under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.  For additional information regarding
 * copyright in this work, please see the NOTICE file in the top level
 * directory of this distribution.
 */
package org.apache.abdera2.common;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URL;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.Set;

import org.apache.abdera2.common.anno.AnnoUtil;
import org.apache.abdera2.common.misc.MultiIterator;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

@SuppressWarnings("unchecked")
public final class Discover {

    private final static Log log = LogFactory.getLog(Discover.class);
    private Discover() {}

    public static <T> T locate(Class<T> _class, String defaultImpl, Object... args) {
        return (T)locate(_class, defaultImpl, getLoader(), args);
    }
    
    public static <T> T locate(String id, String defaultImpl, Object... args) {
        return (T)locate(id, defaultImpl, getLoader(), args);
    }

    public static <T> T locate(Class<T> _class, String defaultImpl, ClassLoader loader, Object... args) {
      try {
        T instance = null, first = null;
        Iterable<T> items = 
          locate(_class, loader, args);
        Iterator<T> is = items.iterator();
        if (defaultImpl == null)
          defaultImpl = AnnoUtil.getDefaultImplementation(_class);
        while (instance == null && is.hasNext()) {
          T i = is.next();
          if (defaultImpl != null && defaultImpl.equals(i.getClass().getName())) {
            instance = i; 
            break;
          } else if (first == null)
            first = i;
        }
        instance = instance != null ? instance : first;
        return instance != null ? 
          instance :
          (T)load(loader, defaultImpl, false, args);
      } catch (Throwable t) {
          throw new RuntimeException(t);
      }      
    }
    
    public static <T> T locate(String id, String defaultImpl, ClassLoader loader, Object... args) {
        try {
            T instance = null;
            Iterable<T> items = 
              locate(id, loader, args);
            for (T i : items) {
                instance = i;
                break;
            }
            return instance != null ? 
              instance :
              (T)load(loader, defaultImpl, false, args);
        } catch (Throwable t) {
            throw new RuntimeException(t);
        }
    }

    private static ClassLoader getLoader() {
        return Thread.currentThread().getContextClassLoader();
    }

    public static <T> Iterable<T> locate(Class<T> _class, ClassLoader cl, Object... args) {
        return locate(_class, false, cl, args);
    }
    
    public static <T> Iterable<T> locate(String id, ClassLoader cl, Object... args) {
        return locate(id, false, cl, args);
    }

    public static <T> Iterable<T> locate(Class<T> _class, boolean classesonly, ClassLoader cl, Object... args) {
      return locate(_class, classesonly, new DefaultLoader<T>(_class, classesonly, args, cl));
    }
    
    public static <T> Iterable<T> locate(String id, boolean classesonly, ClassLoader cl, Object... args) {
        return locate(id, classesonly, new DefaultLoader<T>(id, classesonly, args, cl));
    }

    public static <T> Iterable<T> locate(Class<T> _class, Object...args) {
      return locate(_class, false, args);
    }
    
    public static <T> Iterable<T> locate(String id, Object... args) {
        return locate(id, false, args);
    }

    public static <T> Iterable<T> locate(Class<T> _class, boolean classesonly, Object... args) {
      return locate(new DefaultLoader<T>(_class, classesonly, args));
    }
    
    public static <T> Iterable<T> locate(String id, boolean classesonly, Object... args) {
        return locate(new DefaultLoader<T>(id, classesonly, args));
    }

    public static <T> Iterable<T> locate(Iterable<T> loader) {
        Set<T> impls = new LinkedHashSet<T>();
        try {
            for (T instance : loader) {
              if (instance != null)
                impls.add(instance);
            }
        } catch (Throwable t) {
            log.error(t);
        }
        return impls;
    }

    public static class DefaultLoader<T> implements Iterable<T> {
        protected final ClassLoader loader;
        protected final String id;
        protected final Iterator<T> iterator;
        protected final Object[] args;

        public DefaultLoader(String id, boolean classesonly, Object[] args) {
            this(id, classesonly, args, getLoader());
        }

        public DefaultLoader(String id, boolean classesonly, Object[] args, ClassLoader loader) {
            this.loader = loader != null ? loader : getLoader();
            this.id = id;
            this.args = args;
            this.iterator = init(classesonly);
        }

        public DefaultLoader(Class<T> _class, boolean classesonly, Object[] args, ClassLoader loader) {
          this(_class.getName(), classesonly, args, loader);
        }
        
        public DefaultLoader(Class<T> _class, boolean classesonly, Object[] args) {
          this(_class.getName(), classesonly, args);
        }
        
        private Iterator<T> init(boolean classesonly) {
            try {
                Set<Iterator<T>> list = new HashSet<Iterator<T>>();
                Enumeration<URL> e = locateResources("META-INF/services/" + id, //$NON-NLS-1$ 
                                                     loader,
                                                     Discover.class);
                while (e.hasMoreElements()) {
                    Iterator<T> i =
                        new DefaultLoaderIterator<T>(loader, e.nextElement().openStream(), classesonly, args);
                    list.add(i);
                }
                return new MultiIterator<T>(list);
            } catch (Throwable t) {
                throw new RuntimeException(t);
            }
        }

        public Iterator<T> iterator() {
            return iterator;
        }
    }

    public static class DefaultLoaderIterator<T> extends LineReaderLoaderIterator<T> {
        public DefaultLoaderIterator(ClassLoader cl, InputStream in, boolean classesonly, Object[] args) {
            super(cl, in, classesonly, args);
        }

        public T next() {
            try {
                if (!hasNext())
                    return null;
                return create(read(), args);
            } catch (Throwable t) {
                return null;
            }
        }

        protected T create(String spec, Object[] args) {
            try {
                return (T)load(cl, spec, classesonly, args);
            } catch (RuntimeException e) {
                throw e;
            } catch (Throwable t) {
                throw new RuntimeException(t);
            }
        }
    }

    private static <T> T load(ClassLoader loader, String spec, boolean classesonly, Object[] args) throws Exception {
        if (classesonly) {
            return (T)getClass(loader, spec);
        } else {
            Class<T> _class = getClass(loader, spec);
            Class<?>[] types = new Class<?>[args != null ? args.length : 0];
            if (args != null) {
                for (int n = 0; n < args.length; n++) {
                    types[n] = args[n].getClass();
                }
                return _class.getConstructor(types).newInstance(args);
            } else {
                return _class.newInstance();
            }
        }
    }

    private static <T> Class<T> getClass(ClassLoader loader, String spec) {
        Class<T> c = null;
        try {
            c = (Class<T>)loader.loadClass(spec);
        } catch (ClassNotFoundException e) {
            try {
                // try loading the class from the Discover class loader
                // if the loader failed.
                c = (Class<T>)Discover.class.getClassLoader().loadClass(spec);
            } catch (ClassNotFoundException e1) {
                // throw the original exception
                throw new RuntimeException(e);
            }
        }
        return c;
    }

    public static abstract class LineReaderLoaderIterator<T> extends LoaderIterator<T> {
        private BufferedReader buf = null;
        private String line = null;
        protected final Object[] args;
        protected final boolean classesonly;

        protected LineReaderLoaderIterator(ClassLoader cl, InputStream in, boolean classesonly, Object[] args) {
            super(cl);
            this.args = args;
            this.classesonly = classesonly;
            try {
                InputStreamReader reader = new InputStreamReader(in, "UTF-8");
                buf = new BufferedReader(reader);
                line = readNext();
            } catch (Throwable t) {
                throw new RuntimeException(t);
            }
        }

        public boolean hasNext() {
            return line != null;
        }

        protected String readNext() {
            try {
                String line = null;
                while ((line = buf.readLine()) != null) {
                    line = line.trim();
                    if (!line.startsWith("#"))break; //$NON-NLS-1$
                }
                return line;
            } catch (Throwable t) {
                throw new RuntimeException(t);
            }
        }

        protected String read() {
            String val = line;
            line = readNext();
            return val;
        }
    }

    public static abstract class LoaderIterator<T> implements Iterator<T> {
        protected final ClassLoader cl;

        protected LoaderIterator(ClassLoader cl) {
            this.cl = cl;
        }

        public void remove() {
        }
    }

    public static URL locateResource(String id, ClassLoader loader, Class<?> callingClass) {
        URL url = loader.getResource(id);
        if (url == null && id.startsWith("/"))
            url = loader.getResource(id.substring(1));
        if (url == null)
            url = locateResource(id, Discover.class.getClassLoader(), callingClass);
        if (url == null && callingClass != null)
            url = locateResource(id, callingClass.getClassLoader(), null);
        if (url == null) {
            url = callingClass.getResource(id);
        }
        if ((url == null) && id.startsWith("/")) {
            url = callingClass.getResource(id.substring(1));
        }
        return url;
    }

    public static Enumeration<URL> locateResources(String id, ClassLoader loader, Class<?> callingClass)
        throws IOException {
        Enumeration<URL> urls = loader.getResources(id);
        if (urls == null && id.startsWith("/"))
            urls = loader.getResources(id.substring(1));
        if (urls == null)
            urls = locateResources(id, Discover.class.getClassLoader(), callingClass);
        if (urls == null)
            urls = locateResources(id, callingClass.getClassLoader(), callingClass);
        return urls;
    }

    public static InputStream locateResourceAsStream(String resourceName, ClassLoader loader, Class<?> callingClass) {
        URL url = locateResource(resourceName, loader, callingClass);
        try {
            return (url != null) ? url.openStream() : null;
        } catch (IOException e) {
            return null;
        }
    }
}
