// 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.

import 'dart:collection';

import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/dart/ast/visitor.dart';
import 'package:analyzer/src/generated/engine.dart' show AnalysisContext;
import 'package:analyzer/src/generated/source.dart' show Source;
import 'package:pub_semver/pub_semver.dart';

/// A Dart SDK installed in a specified location.
abstract class DartSdk {
  /// The short name of the dart SDK 'async' library.
  static const String DART_ASYNC = "dart:async";

  /// The short name of the dart SDK 'core' library.
  static const String DART_CORE = "dart:core";

  /// The short name of the dart SDK 'html' library.
  static const String DART_HTML = "dart:html";

  /// The prefix shared by all dart library URIs.
  static const String DART_LIBRARY_PREFIX = "dart:";

  /// The version number that is returned when the real version number could not
  /// be determined.
  static const String DEFAULT_VERSION = "0";

  /// Return the content of the `allowed_experiments.json` file, or `null`
  /// if the file cannot be read, e.g. does not exist.
  String get allowedExperimentsJson;

  /// Return the analysis context used for all of the sources in this [DartSdk].
  AnalysisContext get context;

  /// Return the language version of this SDK, or throws an exception.
  ///
  /// The language version has only major/minor components, the patch number
  /// is always zero, because the patch number does not change the language.
  Version get languageVersion;

  /// Return a list containing all of the libraries defined in this SDK.
  List<SdkLibrary> get sdkLibraries;

  /// Return the revision number of this SDK, or `"0"` if the revision number
  /// cannot be discovered.
  String get sdkVersion;

  /// Return a list containing the library URI's for the libraries defined in
  /// this SDK.
  List<String> get uris;

  /// Return a source representing the given 'file:' [uri] if the file is in
  /// this SDK, or `null` if the file is not in this SDK.
  Source fromFileUri(Uri uri);

  /// Return the library representing the library with the given 'dart:' [uri],
  /// or `null` if the given URI does not denote a library in this SDK.
  SdkLibrary getSdkLibrary(String uri);

  /// Return the source representing the library with the given 'dart:' [uri],
  /// or `null` if the given URI does not denote a library in this SDK.
  Source mapDartUri(String uri);
}

/// Manages the DartSdk's that have been created. Clients need to create
/// multiple SDKs when the analysis options associated with those SDK's contexts
/// will produce different analysis results.
class DartSdkManager {
  /// The absolute path to the directory containing the default SDK.
  final String defaultSdkDirectory;

  /// A table mapping (an encoding of) analysis options and SDK locations to the
  /// DartSdk from that location that has been configured with those options.
  Map<SdkDescription, DartSdk> sdkMap = HashMap<SdkDescription, DartSdk>();

  /// Initialize a newly created manager.
  DartSdkManager(this.defaultSdkDirectory, [@deprecated bool canUseSummaries]);

  /// Return any SDK that has been created, or `null` if no SDKs have been
  /// created.
  DartSdk get anySdk {
    if (sdkMap.isEmpty) {
      return null;
    }
    return sdkMap.values.first;
  }

  /// Return a list of the descriptors of the SDKs that are currently being
  /// managed.
  List<SdkDescription> get sdkDescriptors => sdkMap.keys.toList();

  /// Return the Dart SDK that is appropriate for the given SDK [description].
  /// If such an SDK has not yet been created, then the [ifAbsent] function will
  /// be invoked to create it.
  DartSdk getSdk(SdkDescription description, DartSdk Function() ifAbsent) {
    return sdkMap.putIfAbsent(description, ifAbsent);
  }
}

/// A map from Dart library URI's to the [SdkLibraryImpl] representing that
/// library.
class LibraryMap {
  /// A table mapping Dart library URI's to the library.
  final Map<String, SdkLibraryImpl> _libraryMap = <String, SdkLibraryImpl>{};

  /// Return a list containing all of the sdk libraries in this mapping.
  List<SdkLibrary> get sdkLibraries => List.from(_libraryMap.values);

  /// Return a list containing the library URI's for which a mapping is
  /// available.
  List<String> get uris => _libraryMap.keys.toList();

  /// Return info for debugging https://github.com/dart-lang/sdk/issues/35226.
  Map<String, Object> debugInfo() {
    var map = <String, Object>{};
    for (var uri in _libraryMap.keys) {
      var lib = _libraryMap[uri];
      map[uri] = <String, Object>{
        'path': lib.path,
        'shortName': lib.shortName,
      };
    }
    return map;
  }

  /// Return the library with the given 'dart:' [uri], or `null` if the URI does
  /// not map to a library.
  SdkLibrary getLibrary(String uri) => _libraryMap[uri];

  /// Set the library with the given 'dart:' [uri] to the given [library].
  void setLibrary(String dartUri, SdkLibraryImpl library) {
    _libraryMap[dartUri] = library;
  }

  /// Return the number of library URI's for which a mapping is available.
  int size() => _libraryMap.length;
}

/// A description of a [DartSdk].
class SdkDescription {
  /// The path of the SDK.
  final String path;

  SdkDescription(this.path);

  @override
  int get hashCode {
    return path.hashCode;
  }

  @override
  bool operator ==(Object other) {
    if (other is SdkDescription) {
      return other.path == path;
    }
    return false;
  }

  @override
  String toString() {
    return path;
  }
}

class SdkLibrariesReader_LibraryBuilder extends RecursiveAstVisitor<void> {
  /// The prefix added to the name of a library to form the URI used in code to
  /// reference the library.
  static const String _LIBRARY_PREFIX = "dart:";

  /// The name of the optional parameter used to indicate whether the library is
  /// an implementation library.
  static const String _IMPLEMENTATION = "implementation";

  /// The name of the optional parameter used to specify the path used when
  /// compiling for dart2js.
  static const String _DART2JS_PATH = "dart2jsPath";

  /// The name of the optional parameter used to indicate whether the library is
  /// documented.
  static const String _DOCUMENTED = "documented";

  /// The name of the optional parameter used to specify the category of the
  /// library.
  static const String _CATEGORIES = "categories";

  /// The name of the optional parameter used to specify the platforms on which
  /// the library can be used.
  static const String _PLATFORMS = "platforms";

  /// The value of the [PLATFORMS] parameter used to specify that the library
  /// can be used on the VM.
  static const String _VM_PLATFORM = "VM_PLATFORM";

  /// The library map that is populated by visiting the AST structure parsed
  /// from the contents of the libraries file.
  final LibraryMap _librariesMap = LibraryMap();

  /// Return the library map that was populated by visiting the AST structure
  /// parsed from the contents of the libraries file.
  LibraryMap get librariesMap => _librariesMap;

  // To be backwards-compatible the new categories field is translated to
  // an old approximation.
  String convertCategories(String categories) {
    switch (categories) {
      case "":
        return "Internal";
      case "Client":
        return "Client";
      case "Server":
        return "Server";
      case "Client,Server":
        return "Shared";
      case "Client,Server,Embedded":
        return "Shared";
    }
    return "Shared";
  }

  @override
  void visitMapLiteralEntry(MapLiteralEntry node) {
    String libraryName;
    Expression key = node.key;
    if (key is SimpleStringLiteral) {
      libraryName = "$_LIBRARY_PREFIX${key.value}";
    }
    Expression value = node.value;
    if (value is InstanceCreationExpression) {
      SdkLibraryImpl library = SdkLibraryImpl(libraryName);
      List<Expression> arguments = value.argumentList.arguments;
      for (Expression argument in arguments) {
        if (argument is SimpleStringLiteral) {
          library.path = argument.value;
        } else if (argument is NamedExpression) {
          String name = argument.name.label.name;
          Expression expression = argument.expression;
          if (name == _CATEGORIES) {
            library.category =
                convertCategories((expression as StringLiteral).stringValue);
          } else if (name == _IMPLEMENTATION) {
            library._implementation = (expression as BooleanLiteral).value;
          } else if (name == _DOCUMENTED) {
            library.documented = (expression as BooleanLiteral).value;
          } else if (name == _PLATFORMS) {
            if (expression is SimpleIdentifier) {
              String identifier = expression.name;
              if (identifier == _VM_PLATFORM) {
                library.setVmLibrary();
              } else {
                library.setDart2JsLibrary();
              }
            }
          } else if (name == _DART2JS_PATH) {
            if (expression is SimpleStringLiteral) {
              library.path = expression.value;
            }
          }
        }
      }
      _librariesMap.setLibrary(libraryName, library);
    }
  }
}

/// Represents a single library in the SDK
abstract class SdkLibrary {
  /// Return the name of the category containing the library.
  String get category;

  /// Return `true` if this library can be compiled to JavaScript by dart2js.
  bool get isDart2JsLibrary;

  /// Return `true` if the library is documented.
  bool get isDocumented;

  /// Return `true` if the library is an implementation library.
  bool get isImplementation;

  /// Return `true` if library is internal can be used only by other SDK
  /// libraries.
  bool get isInternal;

  /// Return `true` if this library can be used for both client and server.
  bool get isShared;

  /// Return `true` if this library can be run on the VM.
  bool get isVmLibrary;

  /// Return the path to the file defining the library. The path is relative to
  /// the `lib` directory within the SDK.
  String get path;

  /// Return the short name of the library. This is the URI of the library,
  /// including `dart:`.
  String get shortName;
}

/// The information known about a single library within the SDK.
class SdkLibraryImpl implements SdkLibrary {
  /// The bit mask used to access the bit representing the flag indicating
  /// whether a library is intended to work on the dart2js platform.
  static int DART2JS_PLATFORM = 1;

  /// The bit mask used to access the bit representing the flag indicating
  /// whether a library is intended to work on the VM platform.
  static int VM_PLATFORM = 2;

  @override
  final String shortName;

  /// The path to the file defining the library. The path is relative to the
  /// 'lib' directory within the SDK.
  @override
  String path;

  /// The name of the category containing the library. Unless otherwise
  /// specified in the libraries file all libraries are assumed to be shared
  /// between server and client.
  @override
  String category = "Shared";

  /// A flag indicating whether the library is documented.
  bool _documented = true;

  /// A flag indicating whether the library is an implementation library.
  bool _implementation = false;

  /// An encoding of which platforms this library is intended to work on.
  int _platforms = 0;

  /// Initialize a newly created library to represent the library with the given
  /// [name].
  SdkLibraryImpl(this.shortName);

  /// Set whether the library is documented.
  set documented(bool documented) {
    _documented = documented;
  }

  @override
  bool get isDart2JsLibrary => (_platforms & DART2JS_PLATFORM) != 0;

  @override
  bool get isDocumented => _documented;

  @override
  bool get isImplementation => _implementation;

  @override
  bool get isInternal => category == "Internal";

  @override
  bool get isShared => category == "Shared";

  @override
  bool get isVmLibrary => (_platforms & VM_PLATFORM) != 0;

  /// Record that this library can be compiled to JavaScript by dart2js.
  void setDart2JsLibrary() {
    _platforms |= DART2JS_PLATFORM;
  }

  /// Record that this library can be run on the VM.
  void setVmLibrary() {
    _platforms |= VM_PLATFORM;
  }
}
