// Copyright (c) 2014, 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.

library code_transformer.src.resolver_impl;

import 'dart:async';
import 'package:analyzer/analyzer.dart' show parseCompilationUnit;
import 'package:analyzer/src/generated/ast.dart' hide ConstantEvaluator;
import 'package:analyzer/src/generated/constant.dart' show ConstantEvaluator,
       EvaluationResult;
import 'package:analyzer/src/generated/element.dart';
import 'package:analyzer/src/generated/engine.dart';
import 'package:analyzer/src/generated/java_io.dart';
import 'package:analyzer/src/generated/sdk.dart' show DartSdk;
import 'package:analyzer/src/generated/sdk_io.dart' show DirectoryBasedDartSdk;
import 'package:analyzer/src/generated/source.dart';
import 'package:barback/barback.dart';
import 'package:code_transformers/assets.dart';
import 'package:path/path.dart' as native_path;
import 'package:source_maps/refactor.dart';
import 'package:source_maps/span.dart' show SourceFile, Span;

import 'resolver.dart';

// We should always be using url paths here since it's always Dart/pub code.
final path = native_path.url;

/// Resolves and updates an AST based on Barback-based assets.
///
/// This also provides a handful of useful APIs for traversing and working
/// with the resolved AST.
class ResolverImpl implements Resolver {
  /// Cache of all asset sources currently referenced.
  final Map<AssetId, _AssetBasedSource> sources =
      <AssetId, _AssetBasedSource>{};

  final InternalAnalysisContext _context =
      AnalysisEngine.instance.createAnalysisContext();

  /// Transform for which this is currently updating, or null when not updating.
  Transform _currentTransform;

  /// The currently resolved entry libraries, or null if nothing is resolved.
  List<LibraryElement> _entryLibraries;
  Set<LibraryElement> _libraries;

  /// Future indicating when this resolver is done in the current phase.
  Future _lastPhaseComplete = new Future.value();

  /// Completer for wrapping up the current phase.
  Completer _currentPhaseComplete;

  /// Handler for all Dart SDK (dart:) sources.
  DirectoryBasedDartSdk _dartSdk;

  /// Creates a resolver, where [sdkDir] is the root directory of the Dart SDK,
  /// for resolving `dart:*` imports.
  ResolverImpl(String sdkDir, {AnalysisOptions options}) {
    if (options == null) {
      options = new AnalysisOptionsImpl()
        ..cacheSize = 256 // # of sources to cache ASTs for.
        ..preserveComments = false
        ..analyzeFunctionBodies = true;
    }
    _context.analysisOptions = options;

    _dartSdk = new _DirectoryBasedDartSdkProxy(new JavaFile(sdkDir));
    _dartSdk.context.analysisOptions = options;

    _context.sourceFactory = new SourceFactory([
        new DartUriResolverProxy(_dartSdk),
        new _AssetUriResolver(this)]);
  }

  LibraryElement getLibrary(AssetId assetId) {
    var source = sources[assetId];
    return source == null ? null : _context.computeLibraryElement(source);
  }

  Future<Resolver> resolve(Transform transform, [List<AssetId> entryPoints]) {
    // Can only have one resolve in progress at a time, so chain the current
    // resolution to be after the last one.
    var phaseComplete = new Completer();
    var future = _lastPhaseComplete.whenComplete(() {
      _currentPhaseComplete = phaseComplete;
      return _performResolve(transform,
        entryPoints == null ? [transform.primaryInput.id] : entryPoints);
    }).then((_) => this);
    // Advance the lastPhaseComplete to be done when this phase is all done.
    _lastPhaseComplete = phaseComplete.future;
    return future;
  }

  void release() {
    if (_currentPhaseComplete == null) {
      throw new StateError('Releasing without current lock.');
    }
    _currentPhaseComplete.complete(null);
    _currentPhaseComplete = null;

    // Clear out libraries since they should not be referenced after release.
    _entryLibraries = null;
    _libraries = null;
    _currentTransform = null;
  }

  Future _performResolve(Transform transform, List<AssetId> entryPoints) {
    if (_currentTransform != null) {
      throw new StateError('Cannot be accessed by concurrent transforms');
    }
    _currentTransform = transform;

    // Basic approach is to start at the first file, update it's contents
    // and see if it changed, then walk all files accessed by it.
    var visited = new Set<AssetId>();
    var visiting = new FutureGroup();
    var toUpdate = [];

    void processAsset(AssetId assetId) {
      visited.add(assetId);

      visiting.add(transform.readInputAsString(assetId).then((contents) {
        var source = sources[assetId];
        if (source == null) {
          source = new _AssetBasedSource(assetId, this);
          sources[assetId] = source;
        }
        source.updateDependencies(contents);
        toUpdate.add(new _PendingUpdate(source, contents));
        source.dependentAssets.where((id) => !visited.contains(id))
            .forEach(processAsset);
      }, onError: (e) {
        var source = sources[assetId];
        if (source != null && source.exists()) {
          _context.applyChanges(
              new ChangeSet()..removedSource(source));
          sources[assetId].updateContents(null);
        }
      }));
    }
    entryPoints.forEach(processAsset);

    // Once we have all asset sources updated with the new contents then
    // resolve everything.
    return visiting.future.then((_) {
      var changeSet = new ChangeSet();
      toUpdate.forEach((pending) => pending.apply(changeSet));
      var unreachableAssets = sources.keys.toSet()
          .difference(visited)
          .map((id) => sources[id]);
      for (var unreachable in unreachableAssets) {
        changeSet.removedSource(unreachable);
        unreachable.updateContents(null);
        sources.remove(unreachable.assetId);
      }

      // Update the analyzer context with the latest sources
      _context.applyChanges(changeSet);
      // Force resolve each entry point (the getter will ensure the library is
      // computed first).
      _entryLibraries = entryPoints
          .map((id) => _context.computeLibraryElement(sources[id])).toList();
    });
  }

  Iterable<LibraryElement> get libraries {
    if (_libraries == null) {
      // Note: we don't use `lib.visibleLibraries` because that excludes the
      // exports seen in the entry libraries.
      _libraries = new Set<LibraryElement>();
      _entryLibraries.forEach(_collectLibraries);
    }
    return _libraries;
  }

  void _collectLibraries(LibraryElement lib) {
    if (lib == null || _libraries.contains(lib)) return;
    _libraries.add(lib);
    lib.importedLibraries.forEach(_collectLibraries);
    lib.exportedLibraries.forEach(_collectLibraries);
  }

  LibraryElement getLibraryByName(String libraryName) =>
      libraries.firstWhere((l) => l.name == libraryName, orElse: () => null);

  LibraryElement getLibraryByUri(Uri uri) =>
      libraries.firstWhere((l) => getImportUri(l) == uri, orElse: () => null);

  ClassElement getType(String typeName) {
    var dotIndex = typeName.lastIndexOf('.');
    var libraryName = dotIndex == -1 ? '' : typeName.substring(0, dotIndex);

    var className = dotIndex == -1 ?
        typeName : typeName.substring(dotIndex + 1);

    for (var lib in libraries.where((l) => l.name == libraryName)) {
      var type = lib.getType(className);
      if (type != null) return type;
    }
    return null;
  }

  Element getLibraryVariable(String variableName) {
    var dotIndex = variableName.lastIndexOf('.');
    var libraryName = dotIndex == -1 ? '' : variableName.substring(0, dotIndex);

    var name = dotIndex == -1 ?
        variableName : variableName.substring(dotIndex + 1);

    return libraries.where((lib) => lib.name == libraryName)
        .expand((lib) => lib.units)
        .expand((unit) => unit.topLevelVariables)
        .firstWhere((variable) => variable.name == name,
            orElse: () => null);
  }

  Element getLibraryFunction(String fnName) {
    var dotIndex = fnName.lastIndexOf('.');
    var libraryName = dotIndex == -1 ? '' : fnName.substring(0, dotIndex);

    var name = dotIndex == -1 ?
        fnName : fnName.substring(dotIndex + 1);

    return libraries.where((lib) => lib.name == libraryName)
        .expand((lib) => lib.units)
        .expand((unit) => unit.functions)
        .firstWhere((fn) => fn.name == name,
            orElse: () => null);
  }

  EvaluationResult evaluateConstant(
      LibraryElement library, Expression expression) {
    return new ConstantEvaluator(library.source, _context.typeProvider)
        .evaluate(expression);
  }

  Uri getImportUri(LibraryElement lib, {AssetId from}) =>
      _getSourceUri(lib, from: from);


  /// Similar to getImportUri but will get the part URI for parts rather than
  /// the library URI.
  Uri _getSourceUri(Element element, {AssetId from}) {
    var source = element.source;
    if (source is _AssetBasedSource) {
      return source.getSourceUri(from);
    } else if (source is _DartSourceProxy) {
      return source.uri;
    }
    // Should not be able to encounter any other source types.
    throw new StateError('Unable to resolve URI for ${source.runtimeType}');
  }

  AssetId getSourceAssetId(Element element) {
    var source = element.source;
    if (source is _AssetBasedSource) return source.assetId;
    return null;
  }

  Span getSourceSpan(Element element) {
    var sourceFile = getSourceFile(element);
    if (sourceFile == null) return null;
    return sourceFile.span(element.node.offset, element.node.end);
  }

  TextEditTransaction createTextEditTransaction(Element element) {
    if (element.source is! _AssetBasedSource) return null;

    // Cannot edit unless there is an active transformer.
    if (_currentTransform == null) return null;

    _AssetBasedSource source = element.source;
    // Cannot modify assets in other packages.
    if (source.assetId.package != _currentTransform.primaryInput.id.package) {
      return null;
    }

    var sourceFile = getSourceFile(element);
    if (sourceFile == null) return null;

    return new TextEditTransaction(source.rawContents, sourceFile);
  }

  /// Gets the SourceFile for the source of the element.
  SourceFile getSourceFile(Element element) {
    var assetId = getSourceAssetId(element);
    if (assetId == null) return null;

    var importUri = _getSourceUri(element);
    var spanPath = importUri != null ? importUri.toString() : assetId.path;
    return new SourceFile.text(spanPath, sources[assetId].rawContents);
  }
}

/// Implementation of Analyzer's Source for Barback based assets.
class _AssetBasedSource extends Source {

  /// Asset ID where this source can be found.
  final AssetId assetId;

  /// The resolver this is being used in.
  final ResolverImpl _resolver;

  /// Cache of dependent asset IDs, to avoid re-parsing the AST.
  Iterable<AssetId> _dependentAssets;

  /// The current revision of the file, incremented only when file changes.
  int _revision = 0;

  /// The file contents.
  String _contents;

  _AssetBasedSource(this.assetId, this._resolver);

  /// Update the dependencies of this source. This parses [contents] but avoids
  /// any analyzer resolution.
  void updateDependencies(String contents) {
    if (contents == _contents) return;
    var unit = parseCompilationUnit(contents, suppressErrors: true);
    _dependentAssets = unit.directives
        .where((d) => (d is ImportDirective || d is PartDirective ||
            d is ExportDirective))
        .map((d) => _resolve(assetId, d.uri.stringValue, _logger,
              _getSpan(d, contents)))
        .where((id) => id != null).toSet();
  }

  /// Update the contents of this file with [contents].
  ///
  /// Returns true if the contents of this asset have changed.
  bool updateContents(String contents) {
    if (contents == _contents) return false;
    _contents = contents;
    ++_revision;
    return true;
  }

  /// Contents of the file.
  TimestampedData<String> get contents {
    if (!exists()) throw new StateError('$assetId does not exist');

    return new TimestampedData<String>(modificationStamp, _contents);
  }

  /// Contents of the file.
  String get rawContents => _contents;

  /// Logger for the current transform.
  ///
  /// Only valid while the resolver is updating assets.
  TransformLogger get _logger => _resolver._currentTransform.logger;

  /// Gets all imports/parts/exports which resolve to assets (non-Dart files).
  Iterable<AssetId> get dependentAssets => _dependentAssets;

  bool exists() => _contents != null;

  bool operator ==(Object other) =>
      other is _AssetBasedSource && assetId == other.assetId;

  int get hashCode => assetId.hashCode;

  void getContentsToReceiver(Source_ContentReceiver receiver) {
    receiver.accept(rawContents, modificationStamp);
  }

  String get encoding =>
      "${uriKind.encoding}${assetId.package}/${assetId.path}";

  String get fullName => assetId.toString();

  int get modificationStamp => _revision;

  String get shortName => path.basename(assetId.path);

  UriKind get uriKind {
    if (assetId.path.startsWith('lib/')) return UriKind.PACKAGE_URI;
    return UriKind.FILE_URI;
  }

  bool get isInSystemLibrary => false;

  Source resolveRelative(Uri relativeUri) {
    var id = _resolve(assetId, relativeUri.toString(), _logger, null);
    if (id == null) return null;

    // The entire AST should have been parsed and loaded at this point.
    var source = _resolver.sources[id];
    if (source == null) {
      _logger.error('Could not load asset $id');
    }
    return source;
  }

  /// For logging errors.
  Span _getSpan(AstNode node, [String contents]) =>
      _getSourceFile(contents).span(node.offset, node.end);
  /// For logging errors.
  SourceFile _getSourceFile([String contents]) {
    var uri = getSourceUri();
    var path = uri != null ? uri.toString() : assetId.path;
    return new SourceFile.text(path, contents != null ? contents : rawContents);
  }

  /// Gets a URI which would be appropriate for importing this file.
  ///
  /// Note that this file may represent a non-importable file such as a part.
  Uri getSourceUri([AssetId from]) {
    if (!assetId.path.startsWith('lib/')) {
      // Cannot do absolute imports of non lib-based assets.
      if (from == null) return null;

      if (assetId.package != from.package) return null;
      return new Uri(
          path: path.relative(assetId.path, from: path.dirname(from.path)));
    }

    return Uri.parse('package:${assetId.package}/${assetId.path.substring(4)}');
  }
}

/// Implementation of Analyzer's UriResolver for Barback based assets.
class _AssetUriResolver implements UriResolver {
  final ResolverImpl _resolver;
  _AssetUriResolver(this._resolver);

  Source resolveAbsolute(Uri uri) {
    var assetId = _resolve(null, uri.toString(), logger, null);
    if (assetId == null) {
      logger.error('Unable to resolve asset ID for "$uri"');
      return null;
    }
    var source = _resolver.sources[assetId];
    // Analyzer expects that sources which are referenced but do not exist yet
    // still exist, so just make an empty source.
    if (source == null) {
      source = new _AssetBasedSource(assetId, _resolver);
      _resolver.sources[assetId] = source;
    }
    return source;
  }

  Source fromEncoding(UriKind kind, Uri uri) =>
      throw new UnsupportedError('fromEncoding is not supported');

  Uri restoreAbsolute(Source source) =>
      throw new UnsupportedError('restoreAbsolute is not supported');

  TransformLogger get logger => _resolver._currentTransform.logger;
}


/// Dart SDK which wraps all Dart sources to ensure they are tracked with Uris.
///
/// Just a simple wrapper to make it easy to make sure that all sources we
/// encounter are either _AssetBasedSource or _DartSourceProxy.
class _DirectoryBasedDartSdkProxy extends DirectoryBasedDartSdk {
  _DirectoryBasedDartSdkProxy(JavaFile sdkDirectory) : super(sdkDirectory);

  Source mapDartUri(String dartUri) =>
      _DartSourceProxy.wrap(super.mapDartUri(dartUri), Uri.parse(dartUri));
}


/// Dart SDK resolver which wraps all Dart sources to ensure they are tracked
/// with URIs.
class DartUriResolverProxy implements DartUriResolver {
  final DartUriResolver _proxy;
  DartUriResolverProxy(DirectoryBasedDartSdk sdk) :
      _proxy = new DartUriResolver(sdk);

  Source resolveAbsolute(Uri uri) =>
    _DartSourceProxy.wrap(_proxy.resolveAbsolute(uri), uri);

  DartSdk get dartSdk => _proxy.dartSdk;

  Source fromEncoding(UriKind kind, Uri uri) =>
      throw new UnsupportedError('fromEncoding is not supported');

  Uri restoreAbsolute(Source source) =>
      throw new UnsupportedError('restoreAbsolute is not supported');
}

/// Source file for dart: sources which track the sources with dart: URIs.
///
/// This is primarily to support [Resolver.getImportUri] for Dart SDK (dart:)
/// based libraries.
class _DartSourceProxy implements Source {

  /// Absolute URI which this source can be imported from
  final Uri uri;

  /// Underlying source object.
  final Source _proxy;

  _DartSourceProxy(this._proxy, this.uri);

  /// Ensures that [source] is a _DartSourceProxy.
  static _DartSourceProxy wrap(Source source, Uri uri) {
    if (source == null || source is _DartSourceProxy) return source;
    return new _DartSourceProxy(source, uri);
  }

  Source resolveRelative(Uri relativeUri) {
    // Assume that the type can be accessed via this URI, since these
    // should only be parts for dart core files.
    return wrap(_proxy.resolveRelative(relativeUri), uri);
  }

  bool exists() => _proxy.exists();

  bool operator ==(Object other) =>
    (other is _DartSourceProxy && _proxy == other._proxy);

  int get hashCode => _proxy.hashCode;

  TimestampedData<String> get contents => _proxy.contents;

  String get encoding => _proxy.encoding;

  String get fullName => _proxy.fullName;

  int get modificationStamp => _proxy.modificationStamp;

  String get shortName => _proxy.shortName;

  UriKind get uriKind => _proxy.uriKind;

  bool get isInSystemLibrary => _proxy.isInSystemLibrary;
}

/// Get an asset ID for a URL relative to another source asset.
AssetId _resolve(AssetId source, String url, TransformLogger logger,
    Span span) {
  if (url == null || url == '') return null;
  var uri = Uri.parse(url);

  // Workaround for dartbug.com/17156- pub transforms package: imports from
  // files of the transformers package to have absolute /packages/ URIs.
  if (uri.scheme == '' && path.isAbsolute(url)
      && uri.pathSegments[0] == 'packages') {
    uri = Uri.parse('package:${uri.pathSegments.skip(1).join(path.separator)}');
  }

  if (uri.scheme == 'package') {
    var segments = new List.from(uri.pathSegments);
    var package = segments[0];
    segments[0] = 'lib';
    return new AssetId(package, segments.join(path.separator));
  }
  // Dart SDK libraries do not have assets.
  if (uri.scheme == 'dart') return null;

  return uriToAssetId(source, url, logger, span);
}


/// A completer that waits until all added [Future]s complete.
// TODO(blois): Copied from quiver. Remove from here when it gets
// added to dart:core. (See #6626.)
class FutureGroup<E> {
  static const _FINISHED = -1;

  int _pending = 0;
  Future _failedTask;
  final Completer<List> _completer = new Completer<List>();
  final List results = [];

  /** Gets the task that failed, if any. */
  Future get failedTask => _failedTask;

  /**
   * Wait for [task] to complete.
   *
   * If this group has already been marked as completed, a [StateError] will be
   * thrown.
   *
   * If this group has a [failedTask], new tasks will be ignored, because the
   * error has already been signaled.
   */
  void add(Future task) {
    if (_failedTask != null) return;
    if (_pending == _FINISHED) throw new StateError("Future already completed");

    _pending++;
    var i = results.length;
    results.add(null);
    task.then((res) {
      results[i] = res;
      if (_failedTask != null) return;
      _pending--;
      if (_pending == 0) {
        _pending = _FINISHED;
        _completer.complete(results);
      }
    }, onError: (e, s) {
      if (_failedTask != null) return;
      _failedTask = task;
      _completer.completeError(e, s);
    });
  }

  /**
   * A Future that completes with a List of the values from all the added
   * tasks, when they have all completed.
   *
   * If any task fails, this Future will receive the error. Only the first
   * error will be sent to the Future.
   */
  Future<List<E>> get future => _completer.future;
}

/// A pending update to notify the resolver that a [Source] has been added or
/// changed. This is used by the `_performResolve` algorithm above to apply all
/// changes after it first discovers the transitive closure of files that are
/// reachable from the sources.
class _PendingUpdate {
  _AssetBasedSource source;
  String content;

  _PendingUpdate(this.source, this.content);

  void apply(ChangeSet changeSet) {
    if (!source.updateContents(content)) return;
    if (source._revision == 1 && source._contents != null) {
      changeSet.addedSource(source);
    } else {
      changeSet.changedSource(source);
    }
  }
}
