// Copyright (c) 2016, 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 analyzer.src.generated.package;

import 'dart:collection';

import 'package:analyzer/exception/exception.dart';
import 'package:analyzer/file_system/file_system.dart';
import 'package:analyzer/source/package_map_resolver.dart';
import 'package:analyzer/src/context/builder.dart';
import 'package:analyzer/src/generated/engine.dart';
import 'package:analyzer/src/generated/sdk.dart';
import 'package:analyzer/src/generated/source.dart';
import 'package:analyzer/src/generated/utilities_general.dart';
import 'package:package_config/packages.dart';
import 'package:yaml/yaml.dart';

/**
 * Traverses the package structure to determine the transitive dependencies for
 * a given package.
 */
class DependencyFinder {
  /**
   * The name of the pubspec.yaml file.
   */
  static const String pubspecName = 'pubspec.yaml';

  /**
   * The resource provider used to access the file system.
   */
  final ResourceProvider resourceProvider;

  /**
   * A table mapping the absolute paths of packages to a list of the names of
   * the packages on which those packages depend.
   */
  final Map<String, List<String>> dependencyMap =
      new HashMap<String, List<String>>();

  /**
   * Initialize a newly created dependency finder to use the given
   * [resourceProvider] to access the file system.
   */
  DependencyFinder(this.resourceProvider);

  /**
   * Return a sorted list of the directories containing all of the packages on
   * which the package at the given [packagePath] depends. The [packageMap]
   * maps the names of packages to the directories in which they are contained.
   *
   * Throws an [AnalysisException] if any of the packages are missing their
   * 'pubspec.yaml' file.
   */
  List<String> transitiveDependenciesFor(
      Map<String, List<Folder>> packageMap, String packagePath) {
    Set<String> processedPackages = new HashSet<String>();
    Set<String> processedPaths = new HashSet<String>();
    void process(String packageName) {
      if (processedPackages.add(packageName)) {
        List<Folder> folderList = packageMap[packageName];
        if (folderList == null || folderList.isEmpty) {
          throw new StateError('No mapping for package "$packageName"');
        }
        String packagePath = folderList[0].path;
        processedPaths.add(packagePath);
        List<String> dependencies = _dependenciesFor(packagePath);
        for (String dependency in dependencies) {
          process(dependency);
        }
      }
    }

    List<String> dependencies = _dependenciesFor(packagePath);
    dependencies.forEach(process);
    processedPaths.remove(packagePath);
    List<String> transitiveDependencies = processedPaths.toList();
    transitiveDependencies.sort();
    return transitiveDependencies;
  }

  /**
   * Add to the given set of [dependecies] all of the package names used as keys
   * in the given [yamlMap].
   */
  void _collectDependencies(HashSet<String> dependencies, YamlMap yamlMap) {
    if (yamlMap is Map) {
      for (var key in yamlMap.keys) {
        if (key is String) {
          dependencies.add(key);
        }
      }
    }
  }

  /**
   * Return a list of the names of the packages on which the package at the
   * [packagePath] depends.
   */
  List<String> _dependenciesFor(String packagePath) {
    return dependencyMap.putIfAbsent(packagePath, () {
      Set<String> dependencies = new HashSet<String>();
      YamlNode yamlNode = _readPubspec(packagePath);
      if (yamlNode is YamlMap) {
        _collectDependencies(dependencies, yamlNode['dependencies']);
      }
      return dependencies.toList();
    });
  }

  /**
   * Read the content of the pubspec file in the directory at the given
   * [directoryPath]. Return `null` if the file does not exist, cannot be read,
   * or has content that is not valid YAML.
   */
  YamlNode _readPubspec(String directoryPath) {
    try {
      File yamlFile = resourceProvider
          .getFolder(directoryPath)
          .getChildAssumingFile(pubspecName);
      String yamlContent = yamlFile.readAsStringSync();
      return loadYamlNode(yamlContent);
    } catch (exception, stackTrace) {
      throw new AnalysisException('Missing $pubspecName in $directoryPath',
          new CaughtException(exception, stackTrace));
    }
  }
}

/**
 * A description of the context in which a package will be analyzed.
 */
class PackageDescription {
  /**
   * The id of the package being described. The id encodes the actual locations
   * of the package itself and all of the packages on which it depends.
   */
  final String id;

  /**
   * The SDK against which the package will be analyzed.
   */
  final DartSdk sdk;

  /**
   * The analysis options that will be used when analyzing the package.
   */
  final AnalysisOptions options;

  /**
   * Initialize a newly create package description to describe the package with
   * the given [id] that is being analyzed against the given [sdk] using the
   * given [options].
   */
  PackageDescription(this.id, this.sdk, this.options);

  @override
  int get hashCode {
    int hashCode = 0;
    for (int value in options.signature) {
      hashCode = JenkinsSmiHash.combine(hashCode, value);
    }
    hashCode = JenkinsSmiHash.combine(hashCode, id.hashCode);
    hashCode = JenkinsSmiHash.combine(hashCode, sdk.hashCode);
    return JenkinsSmiHash.finish(hashCode);
  }

  @override
  bool operator ==(Object other) {
    return other is PackageDescription &&
        other.sdk == sdk &&
        AnalysisOptions.signaturesEqual(
            other.options.signature, options.signature) &&
        other.id == id;
  }
}

/**
 * Manages the contexts in which each package is analyzed.
 */
class PackageManager {
  /**
   * The resource provider used to access the file system.
   */
  final ResourceProvider resourceProvider;

  /**
   * A table mapping the id's of packages to the context in which the package is
   * analyzed.
   */
  final Map<PackageDescription, AnalysisContext> contextMap =
      new HashMap<PackageDescription, AnalysisContext>();

  /**
   * Initialize a newly created package manager.
   */
  PackageManager(this.resourceProvider);

  /**
   * Return the context in which the package at the given [packagePath] should
   * be analyzed when the given [packages] object is used to resolve package
   * names, the given [resolver] will be used to resolve 'dart:' URI's, and the
   * given [options] will control the analysis.
   */
  AnalysisContext getContext(String packagePath, Packages packages,
      DartUriResolver resolver, AnalysisOptions options) {
    DartSdk sdk = resolver.dartSdk;
    Map<String, List<Folder>> packageMap =
        new ContextBuilder(resourceProvider, null, null)
            .convertPackagesToMap(packages);
    PackageDescription description =
        new PackageDescription(_buildId(packagePath, packageMap), sdk, options);
    return contextMap.putIfAbsent(description, () {
      AnalysisContext context = AnalysisEngine.instance.createAnalysisContext();
      context.sourceFactory = new SourceFactory(<UriResolver>[
        resolver,
        new PackageMapUriResolver(resourceProvider, packageMap),
        new ResourceUriResolver(resourceProvider)
      ], packages, resourceProvider);
      context.analysisOptions = options;
      return context;
    });
  }

  /**
   * Return the id associated with the package at the given [packagePath] when
   * the given [packageMap] is used to resolve package names.
   */
  String _buildId(String packagePath, Map<String, List<Folder>> packageMap) {
    DependencyFinder finder = new DependencyFinder(resourceProvider);
    List<String> dependencies =
        finder.transitiveDependenciesFor(packageMap, packagePath);
    StringBuffer buffer = new StringBuffer();
    buffer.write(packagePath);
    for (String dependency in dependencies) {
      buffer.write(';');
      buffer.write(dependency);
    }
    return buffer.toString();
  }
}
