// Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

package com.google.dart.compiler;

import java.io.File;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;


/**
 * Manages the collection of {@link SystemLibrary}s.
 */
public class PackageLibraryManager {

  public static class NotADartShortUriException extends RuntimeException {
    private static final long serialVersionUID = 1L;

    public NotADartShortUriException(String uriString) {
      super("Expected dart:<short name>, got: " + uriString);
    }

    public NotADartShortUriException(URI uri) {
      super("Expected dart:<short name>, got: " + uri.toString());
    }
  }

  /**
   * The "any" platform is meant to have definitions for all known dart system libraries.
   * Other implementations may only contain a subset.
   */
  public static final String DEFAULT_PLATFORM = "any";
  public static final File DEFAULT_SDK_PATH = new File(System.getProperty(
      "com.google.dart.sdk", "../"));
  
  public static final File DEFAULT_PACKAGE_ROOT = new File("packages");
  public static final List<File> DEFAULT_PACKAGE_ROOTS = Arrays.asList(new File[] {DEFAULT_PACKAGE_ROOT});

  public static final String PACKAGE_SCHEME = "package";
  public static final String PACKAGE_SCHEME_SPEC = "package:";

  public static final String DART_SCHEME = "dart";
  public static final String DART_SCHEME_SPEC = "dart:";
  

  /**
   * Answer <code>true</code> if the string is a dart spec
   */
  public static boolean isDartSpec(String spec) {
    return spec != null && spec.startsWith(DART_SCHEME_SPEC);
  }

  /**
   * Answer <code>true</code> if the specified URI has a "dart" scheme
   */
  public static boolean isDartUri(URI uri) {
    return uri != null && DART_SCHEME.equals(uri.getScheme());
  }

  /**
   * Answer <code>true</code> if the string is a package spec
   */
  public static boolean isPackageSpec(String spec) {
    return spec != null && spec.startsWith(PACKAGE_SCHEME_SPEC);
  }

  /**
   * Answer <code>true</code> if the specified URI has a "package" scheme
   */
  public static boolean isPackageUri(URI uri) {
    return uri != null && PACKAGE_SCHEME.equals(uri.getScheme());
  }

  private static SystemLibraryManager SDK_LIBRARY_MANAGER;
  
  private List<File> packageRoots = new ArrayList<File>();
  private List<URI> packageRootsUri = new ArrayList<URI>(); 

  public PackageLibraryManager() {
    this(DEFAULT_SDK_PATH, DEFAULT_PLATFORM);
  }

  public PackageLibraryManager(File sdkPath, String platformName) {
    this(new FileBasedSystemLibraryProvider(sdkPath));
  }

  public PackageLibraryManager(SystemLibraryProvider libraryProvider) {
    initLibraryManager(libraryProvider);
    setPackageRoots(DEFAULT_PACKAGE_ROOTS);
  }
  
  protected void initLibraryManager(SystemLibraryProvider libraryProvider) {
    if (SDK_LIBRARY_MANAGER == null) {
      SDK_LIBRARY_MANAGER = new SystemLibraryManager(libraryProvider);
    }
  }


  /**
   * Expand a relative or short URI (e.g. "dart:html") which is implementation independent to its
   * full URI (e.g. "dart://html/com/google/dart/htmllib/html.dart").
   *
   * @param uri the relative URI
   * @return the expanded URI
   *  or the original URI if it could not be expanded
   *  or null if the uri is of the form "dart:<libname>" but does not correspond to a system library
   */
  public URI expandRelativeDartUri(URI uri) throws AssertionError {
    if (isDartUri(uri)) {
      return SDK_LIBRARY_MANAGER.expandRelativeDartUri(uri);
    } 
    if (isPackageUri(uri)){
      String host = uri.getHost();
      if (host == null) {
        String spec = uri.getSchemeSpecificPart();
        if (!spec.startsWith("//")){
          try {
            if (spec.startsWith("/")){
              // TODO(keertip): fix to handle spaces
              uri = new URI(PACKAGE_SCHEME + ":/" + spec);
            } else {
              uri = new URI(PACKAGE_SCHEME + "://" + spec);
            } 
          } catch (URISyntaxException e) {
            throw new AssertionError();
          }
        }       
      }
    }
    return uri;
  }

 
  
  /**
   * Given an absolute file URI (e.g. "file:/some/install/directory/dart-sdk/lib/core/bool.dart"),
   *  answer the corresponding dart: URI (e.g. "dart://core/bool.dart") for that file URI,
   *  or <code>null</code> if the file URI does not map to a dart: URI 
   * @param fileUri the file URI
   * @return the dart URI or <code>null</code>
   */
  public URI getRelativeUri(URI fileUri) {
    // TODO (danrubel): does not convert dart: libraries outside the dart-sdk/lib directory
    if (fileUri == null || !fileUri.getScheme().equals("file")) {
      return null;
    }
   
    URI relativeUri = SDK_LIBRARY_MANAGER.getRelativeUri(fileUri);
    if (relativeUri != null){
      return relativeUri;
    }
    
    for (URI rootUri : packageRootsUri){
      relativeUri = rootUri.relativize(fileUri);
        if (relativeUri.getScheme() == null) {
          try {
            return new URI(null, null, "package://" + relativeUri.getPath(), null, null);
          } catch (URISyntaxException e) {
        //$FALL-THROUGH$
        }
      }
    }
    return null;
  }

  /**
   * Given a package URI (package:foo/foo.dart), convert it into a file system URI.
   */
  public URI resolvePackageUri(String packageUriRef) {
    if (packageUriRef.startsWith(PACKAGE_SCHEME_SPEC)) {
      String relPath = packageUriRef.substring(PACKAGE_SCHEME_SPEC.length());
      if (relPath.startsWith("/")){
        relPath = relPath.replaceAll("^\\/+", "");
      }
      for (URI rootUri : packageRootsUri){
        URI fileUri = rootUri.resolve(relPath);
        File file = new File(fileUri);
        if (file.exists()){
          try {
            return file.getCanonicalFile().toURI();
          } catch (IOException e) {
            file.toURI();
          }
        }
      }
      // don't return null for package scheme
      return packageRootsUri.get(0).resolve(relPath);
    }
   return null; 
  }

  /**
   * Answer the original "dart:<libname>" URI for the specified resolved URI or <code>null</code> if
   * it does not map to a short URI.
   */
  public URI getShortUri(URI uri) {
    URI shortUri = SDK_LIBRARY_MANAGER.getShortUri(uri);
    if (shortUri != null){
      return shortUri;
    }
    shortUri = getRelativeUri(uri);
    if (shortUri != null){
      try {
        return new URI(null, null, shortUri.getScheme() + ":" +  shortUri.getHost() + shortUri.getPath(),null, null);
      } catch (URISyntaxException e) {
      }
    }
    return null;
  }

  /**
   * Expand a relative or short URI (e.g. "dart:html") which is implementation independent to its
   * full URI (e.g. "dart://html/com/google/dart/htmllib/html.dart") and then translate that URI to
   * a "file:"  URI (e.g.
   * "file:/some/install/directory/com/google/dart/htmllib/html.dart").
   *
   * @param uri the original URI
   * @return the expanded and translated URI, which may be <code>null</code> and may not exist
   * @exception RuntimeException if the URI is a "dart" scheme, but does not map to a defined system
   *     library
   */
  public URI resolveDartUri(URI uri) {
    return translateDartUri(expandRelativeDartUri(uri));
  }
  
  
  public List<File> getPackageRoots(){
    return packageRoots;
  }
  
  
  public void setPackageRoots(List<File> roots){
    if (roots == null || roots.isEmpty()){
      roots = DEFAULT_PACKAGE_ROOTS;
    }
    packageRoots.clear();
    for (File file : roots){   
      packageRoots.add(file.getAbsoluteFile());
    }   
    packageRootsUri.clear();
    for (File file : roots){
      packageRootsUri.add(file.toURI());
    }
  }
  
  /**
   * Translate the URI from dart://[host]/[pathToLib] (e.g. dart://html/html.dart)
   * to a "file:" URI (e.g. "file:/some/install/directory/html.dart")
   *
   * @param uri the original URI
   * @return the translated URI, which may be <code>null</code> and may not exist
   * @exception RuntimeException if the URI is a "dart" scheme,
   *     but does not map to a defined system library
   */
  public URI translateDartUri(URI uri) {
    if (isDartUri(uri)) {
     return SDK_LIBRARY_MANAGER.translateDartUri(uri);
    } 
    if (isPackageUri(uri)){   
      URI fileUri;
      for (URI rootUri : packageRootsUri){
        fileUri = getResolvedPackageUri(uri, rootUri);
        File file  = new File(fileUri);
        if (file.exists()){
          try {
            return file.getCanonicalFile().toURI();
          } catch (IOException e) {
            return file.toURI();
          }
        }
      }
      // resolve against first package root
      fileUri = getResolvedPackageUri(uri, packageRootsUri.get(0));
      return fileUri;
    }
    return uri;
  }

  
  /**
   * Given a uri, resolve against the list of package roots, used to find generated files
   * @return uri - resolved uri if file exists, else return given uri 
   */
  public URI findExistingFileInPackages(URI fileUri){
    
    URI resolvedUri = getRelativeUri(fileUri);
    if (isPackageUri(resolvedUri)){
      resolvedUri = resolvePackageUri(resolvedUri.toString());
      return resolvedUri;
    }
    return fileUri;
  }

  /**
   * Resolves the given uri against the package root uri
   */
  private URI getResolvedPackageUri(URI uri, URI packageRootUri) {
    URI fileUri;
    // TODO(keertip): Investigate further
    // if uri.getHost() returns null, then it is resolved right
    // so use uri.getAuthority to resolve
    // package://third_party/dart_lang/lib/unittest/unittest.dart
    if (uri.getHost() != null){
      fileUri =  packageRootUri.resolve(uri.getHost() + uri.getPath());
    } else {
      fileUri = packageRootUri.resolve(uri.getAuthority() + uri.getPath());
    }
    return fileUri;
  }

  /**
   * Answer a collection of all bundled library URL specs (e.g. "dart:html").
   *
   * @return a collection of specs (not <code>null</code>, contains no <code>null</code>s)
   */
  public Collection<String> getAllLibrarySpecs() {
    return SDK_LIBRARY_MANAGER.getAllLibrarySpecs();
  }
  
  protected SystemLibrary[] getDefaultLibraries() {
    return SDK_LIBRARY_MANAGER.getDefaultLibraries(); 
  }
  
  public Collection<SystemLibrary> getSystemLibraries(){
    return SDK_LIBRARY_MANAGER.getAllSystemLibraries();
  }

  /**
   * Check if this URI denotes a patch file.
   */
  public static boolean isPatchFile(File file) {
    return SDK_LIBRARY_MANAGER.isPatchFile(file.toURI());
  } 
  
}
