// 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 com.google.dart.compiler.SystemLibrariesReader.DartLibrary;

import java.io.File;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

/**
 * A Library manager that manages system libraries 
 */
public class SystemLibraryManager  {
  
  private HashMap<String, String> expansionMap;
  private Map<String, SystemLibrary> hostMap;
  private final URI sdkLibPathUri;
  
  private Map<URI, URI> longToShortUriMap;

  private List<SystemLibrary> libraries;
  private final SystemLibraryProvider libraryProvider;

  public SystemLibraryManager(File sdkPath) {
    this(new FileBasedSystemLibraryProvider(sdkPath));  
  }

  public SystemLibraryManager(SystemLibraryProvider libraryProvider) {
    this.libraryProvider = libraryProvider;
    this.sdkLibPathUri = libraryProvider.getSdkLibPathUri();
    setLibraries(getDefaultLibraries());
  }
  
  public URI expandRelativeDartUri(URI uri) throws AssertionError {
      String host = uri.getHost();
      if (host == null && uri.getAuthority() == null) {
        String spec = uri.getSchemeSpecificPart();
        String replacement = expansionMap.get(spec);
        if (replacement != null) {
          try {
            uri = new URI(PackageLibraryManager.DART_SCHEME + ":" + replacement);
          } catch (URISyntaxException e) {
            throw new AssertionError();
          }
        } else {
          return null;
        }
      }
      return uri;
  }
  
  public URI getRelativeUri(URI fileUri) {
    
    if (fileUri == null || !fileUri.getScheme().equals("file")){
      return null;
    }
  
    URI relativeUri = sdkLibPathUri.relativize(fileUri);
    if (relativeUri.getScheme() == null) {
      try {
        return new URI(null, null, "dart://" + relativeUri.getPath(), null, null);
      } catch (URISyntaxException e) {
        //$FALL-THROUGH$
      }
    } 
    return null;
  }
  
  public URI getShortUri(URI uri) {
    URI shortUri = longToShortUriMap.get(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;
  }
  
  public URI translateDartUri(URI uri) {
   
      String host = uri.getHost();
      
      SystemLibrary library = hostMap.get(host);
      if (library != null) {
        return library.translateUri(uri);
      }
      if (host != null) {        
        return libraryProvider.resolveHost(host, uri);
      }
      String authorithy = uri.getAuthority();
      if (authorithy != null){
        return libraryProvider.resolveHost(authorithy, uri);
      }
      throw new RuntimeException("No system library defined for " + uri);
   
  }
  
  
  public Collection<String> getAllLibrarySpecs() {
    Collection<String> result = new ArrayList<String>(libraries.size());
    for (SystemLibrary lib : libraries) {
      result.add("dart:" + lib.getShortName());
    }
    return result;
  }
  
  public Collection<SystemLibrary> getAllSystemLibraries(){
    return libraries;
  }
  
  /**
   * Load the libraries listed out in the libraries.dart files as read by the {@link SystemLibrariesReader}
   */
  protected SystemLibrary[] getDefaultLibraries() {
    libraries = new ArrayList<SystemLibrary>();
    longToShortUriMap = new HashMap<URI, URI>();

    // Cycle through the import.config, extracting explicit mappings and searching directories
    URI base = this.sdkLibPathUri;
    
    Map<String, DartLibrary> declaredLibraries = libraryProvider.getLibraryMap();
    
    HashSet<String> explicitShortNames = new HashSet<String>();
    
    for (Entry<String, DartLibrary> entry : declaredLibraries.entrySet()) {
      if (entry.getValue().getCategory().equals("Internal")
          // TODO(8365): the following line allows dart:_collection-dev to
          // be imported even though it's a hidden library.
          && !entry.getKey().equals("dart:_collection-dev")) {
        continue;
      }
      String shortName = entry.getKey().trim();
      DartLibrary library = entry.getValue();
      String path = library.getPath();
      URI libFileUri;
      try {
        libFileUri = base.resolve(new URI(null, null, path, null, null)).normalize();
      } catch (URISyntaxException e) {
        continue;
      }
      
      if (!libraryProvider.exists(libFileUri)) {
        throw new InternalCompilerException("Can't find system library dart:" + shortName
          + " at " + libFileUri);
      }
      
      int index = shortName.indexOf(':');
      if (index == -1) {
        continue;
      }
      explicitShortNames.add(shortName);
      String scheme = shortName.substring(0, index + 1);
      String name = shortName.substring(index + 1);
      
      String relPath = sdkLibPathUri.relativize(libFileUri).getPath();
      index = relPath.indexOf('/');
      if (index == -1) {
        continue;
      }
      String host = relPath.substring(0, index);
      String pathToLib = relPath.substring(index + 1);
      
      addLib(scheme, 
          host, 
          name, 
          pathToLib, 
          library.getCategory(),
          library.isDocumented(), 
          library.isImplementation());
      
    }
    return libraries.toArray(new SystemLibrary[libraries.size()]);
  }
  
  protected boolean addLib(String scheme, String host, String name, String pathToLib, 
                          String category, boolean documented, boolean implementation)
      throws AssertionError {
    
    SystemLibrary lib = libraryProvider.createSystemLibrary(name, host, pathToLib, category, documented, implementation);
    libraries.add(lib);
    
    String libSpec = scheme + name;
    URI libUri;
    URI expandedUri;
    try {
      libUri = new URI(libSpec);
      expandedUri = new URI("dart:" + "//" + host + "/" + pathToLib);
    } catch (URISyntaxException e) {
      throw new AssertionError(e);
    }
    URI resolvedUri = lib.translateUri(expandedUri);
    longToShortUriMap.put(resolvedUri, libUri);
    longToShortUriMap.put(expandedUri, libUri);
    return true;
  }

  /**
   * Register system libraries for the "dart:" protocol such that dart:[shortLibName] (e.g.
   * "dart:html") will automatically be expanded to dart://[host]/[pathToLib] (e.g.
   * dart://html/html.dart)
   */
  private void setLibraries(SystemLibrary[] newLibraries) {
    libraries = new ArrayList<SystemLibrary>();
    hostMap = new HashMap<String, SystemLibrary>();
    expansionMap = new HashMap<String, String>();
    for (SystemLibrary library : newLibraries) {
      String host = library.getHost();
      SystemLibrary existingLib = hostMap.get(host);
      if (existingLib != null) {
        libraries.remove(existingLib);
      }
      libraries.add(library);
      hostMap.put(host, library);
      expansionMap.put(library.getShortName(),
          "//" + host + "/" + library.getPathToLib());
    }
  }

  /**
   * Check if this URI denotes a patch file.
   */
  public boolean isPatchFile(URI uri) {
    return libraryProvider.isPatchFile(uri);
  }

}
