/*
 * Copyright 2011 Google Inc.
 *
 * Licensed 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.
 */
package com.google.gwt.dev.cfg;

import static com.google.gwt.thirdparty.guava.common.base.StandardSystemProperty.JAVA_CLASS_PATH;

import com.google.gwt.thirdparty.guava.common.base.Splitter;

import java.io.File;
import java.net.MalformedURLException;
import java.net.URL;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;

/**
 * Creates instances of {@link ResourceLoader}.
 */
public class ResourceLoaders {

  private static class ClassLoaderAdapter implements ResourceLoader {
    private final ClassLoader wrapped;

    public ClassLoaderAdapter(ClassLoader wrapped) {
      // TODO(rluble): Maybe stop wrapping arbitrary class loaders here and always use the
      // system ClassLoader.
      this.wrapped = wrapped;
    }

    @Override
    public boolean equals(Object other) {
      if (!(other instanceof ClassLoaderAdapter)) {
        return false;
      }
      ClassLoaderAdapter otherAdapter = (ClassLoaderAdapter) other;
      return wrapped.equals(otherAdapter.wrapped);
    }

    /**
     * Returns the URLs for the system class path.
     */
    @Override
    public List<URL> getClassPath() {
      List<URL> result = new ArrayList<URL>();
      for (String entry : Splitter.on(File.pathSeparatorChar).split(JAVA_CLASS_PATH.value())) {
        try {
          result.add(Paths.get(entry).toUri().toURL());
        } catch (MalformedURLException e) {
        }
      }
      return result;
    }

    @Override
    public URL getResource(String resourceName) {
      return wrapped.getResource(resourceName);
    }

    @Override
    public int hashCode() {
      return wrapped.hashCode();
    }
  }

  /**
   * A ResourceLoader that prefixes some directories to another ResourceLoader.
   */
  private static class PrefixLoader implements ResourceLoader {
    private final List<File> path;
    private final List<URL> pathAsUrls = new ArrayList<URL>();
    private final ResourceLoader fallback;

    public PrefixLoader(List<File> path, ResourceLoader fallback) {
      assert path != null;
      this.path = path;
      this.fallback = fallback;
      for (File file : path) {
        try {
          pathAsUrls.add(file.toURI().toURL());
        } catch (MalformedURLException e) {
          throw new RuntimeException("can't create URL for file: " + file);
        }
      }
    }

    @Override
    public boolean equals(Object other) {
      if (!(other instanceof PrefixLoader)) {
        return false;
      }
      PrefixLoader otherLoader = (PrefixLoader) other;
      return path.equals(otherLoader.path) && fallback.equals(otherLoader.fallback);
    }

    @Override
    public List<URL> getClassPath() {
      List<URL> result = new ArrayList<URL>();
      result.addAll(pathAsUrls);
      result.addAll(fallback.getClassPath());
      return result;
    }

    @Override
    public URL getResource(String resourceName) {
      for (File prefix : path) {
        File candidate = new File(prefix, resourceName);
        if (candidate.exists()) {
          try {
            return candidate.toURI().toURL();
          } catch (MalformedURLException e) {
            return null;
          }
        }
      }
      return fallback.getResource(resourceName);
    }

    @Override
    public int hashCode() {
      return path.hashCode() ^ fallback.hashCode();
    }
  }

  /**
   * Creates a ResourceLoader that loads from the given thread's class loader.
   */
  public static ResourceLoader forClassLoader(Thread thread) {
    return wrap(thread.getContextClassLoader());
  }

  /**
   * Creates a ResourceLoader that loads from a list of directories and falls back
   * to another ResourceLoader.
   */
  public static ResourceLoader forPathAndFallback(List<File> path, ResourceLoader fallback) {
    return new PrefixLoader(path, fallback);
  }

  /**
   * Adapts a ClassLoader to work as a ResourceLoader.
   * (Caveat: any ClassLoader in the chain that isn't a URLClassLoader won't contribute to the
   * results of {@link  ResourceLoader#getClassPath}.)
   */
  public static ResourceLoader wrap(ClassLoader loader) {
    return new ClassLoaderAdapter(loader);
  }

  private ResourceLoaders() {
  }
}
