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

import 'package:analyzer/src/generated/utilities_dart.dart';
import 'package:analyzer/src/summary/format.dart';
import 'package:analyzer/src/summary/idl.dart';
import 'package:analyzer/src/summary/name_filter.dart';

/**
 * Create a [LinkedLibraryBuilder] corresponding to the given [definingUnitUri]
 * and [definingUnit], which should be the defining compilation unit for a
 * library. Compilation units referenced by the defining compilation unit via
 * `part` declarations will be retrieved using [getPart].  Public namespaces
 * for libraries referenced by the defining compilation unit via `import`
 * declarations (and files reachable from them via `part` and `export`
 * declarations) will be retrieved using [getImport].
 */
LinkedLibraryBuilder prelink(
    String definingUnitUri,
    UnlinkedUnit definingUnit,
    GetPartCallback getPart,
    GetImportCallback getImport,
    GetDeclaredVariable getDeclaredVariable) {
  return new _Prelinker(definingUnitUri, definingUnit, getPart, getImport,
          getDeclaredVariable)
      .prelink();
}

/**
 * Return the raw string value of the variable with the given [name],
 * or `null` of the variable is not defined.
 */
typedef String GetDeclaredVariable(String name);

/**
 * Type of the callback used by the prelinker to obtain public namespace
 * information about libraries with the given [absoluteUri] imported by the
 * library to be prelinked (and the transitive closure of parts and exports
 * reachable from those libraries).
 *
 * If no file exists at the given uri, `null` should be returned.
 */
typedef UnlinkedPublicNamespace GetImportCallback(String absoluteUri);

/**
 * Type of the callback used by the prelinker to obtain unlinked summaries of
 * part files of the library to be prelinked.
 *
 * If no file exists at the given uri, `null` should be returned.
 */
typedef UnlinkedUnit GetPartCallback(String absoluteUri);

/**
 * A [_Meaning] representing a class.
 */
class _ClassMeaning extends _Meaning {
  final _Namespace namespace;

  _ClassMeaning(int unit, int dependency, int numTypeParameters, this.namespace)
      : super(unit, ReferenceKind.classOrEnum, dependency, numTypeParameters);
}

/**
 * A [_Meaning] stores all the information necessary to find the declaration
 * referred to by a name in a namespace.
 */
class _Meaning {
  /**
   * Which unit in the dependent library contains the declared entity.
   */
  final int unit;

  /**
   * The kind of entity being referred to.
   */
  final ReferenceKind kind;

  /**
   * Which of the dependencies of the library being prelinked contains the
   * declared entity.
   */
  final int dependency;

  /**
   * If the entity being referred to is generic, the number of type parameters
   * it accepts.  Otherwise zero.
   */
  final int numTypeParameters;

  _Meaning(this.unit, this.kind, this.dependency, this.numTypeParameters);

  /**
 * Encode this [_Meaning] as a [LinkedExportName], using the given [name].
 */
  LinkedExportName encodeExportName(String name) {
    return new LinkedExportNameBuilder(
        name: name, dependency: dependency, unit: unit, kind: kind);
  }

/**
   * Encode this [_Meaning] as a [LinkedReference].
   */
  LinkedReferenceBuilder encodeReference() {
    return new LinkedReferenceBuilder(
        unit: unit,
        kind: kind,
        dependency: dependency,
        numTypeParameters: numTypeParameters);
  }
}

/**
 * Mapping from names to corresponding unique [_Meaning]s.
 */
class _Namespace {
  final Set<String> namesWithConflictingDefinitions = new Set<String>();
  final Set<String> libraryNames = new Set<String>();
  final Map<String, _Meaning> map = <String, _Meaning>{};

  /**
   * Return the [_Meaning] of the name, or `null` is not defined.
   */
  _Meaning operator [](String name) {
    return map[name];
  }

  /**
   * Define that the [name] has the given [value].  If the [name] already been
   * defined with a different value, then it becomes undefined.
   */
  void add(String name, _Meaning value) {
    // Already determined to be a conflict.
    if (namesWithConflictingDefinitions.contains(name)) {
      return;
    }

    _Meaning currentValue = map[name];
    if (currentValue == null) {
      map[name] = value;
    } else if (currentValue == value) {
      // The same value, ignore.
    } else {
      // A conflict, remember it, and un-define the name.
      namesWithConflictingDefinitions.add(name);
      map.remove(name);
    }
  }

  /**
   * Return `true` if the [name] was defined before [rememberLibraryNames]
   * invocation.
   */
  bool definesLibraryName(String name) => libraryNames.contains(name);

  /**
   * Return `true` if the [name] is already defined.
   */
  bool definesName(String name) => map.containsKey(name);

  /**
   * Apply [f] to each name-meaning pair.
   */
  void forEach(void f(String key, _Meaning value)) {
    map.forEach(f);
  }

  /**
   * This method should be invoked after defining all names that are defined
   * in a library, before defining imported names.
   */
  void rememberLibraryNames() {
    libraryNames.addAll(map.keys);
  }
}

/**
 * A [_Meaning] representing a prefix introduced by an import directive.
 */
class _PrefixMeaning extends _Meaning {
  final _Namespace namespace = new _Namespace();

  _PrefixMeaning() : super(0, ReferenceKind.prefix, 0, 0);
}

/**
 * Helper class containing temporary data structures needed to prelink a single
 * library.
 */
class _Prelinker {
  final String definingUnitUri;
  final UnlinkedUnit definingUnit;
  final GetPartCallback getPart;
  final GetImportCallback getImport;
  final GetDeclaredVariable getDeclaredVariable;

  /**
   * Cache of values returned by [getImport].
   */
  final Map<String, UnlinkedPublicNamespace> importCache =
      <String, UnlinkedPublicNamespace>{};

  /**
   * Cache of values returned by [getPart].
   */
  final Map<String, UnlinkedUnit> partCache = <String, UnlinkedUnit>{};

  /**
   * Names defined inside the library being prelinked.
   */
  final _Namespace privateNamespace = new _Namespace()
    ..add('dynamic', new _Meaning(0, ReferenceKind.classOrEnum, 0, 0))
    ..add('void', new _Meaning(0, ReferenceKind.classOrEnum, 0, 0));

  /**
   * List of dependencies of the library being prelinked.  This will be output
   * to [LinkedLibrary.dependencies].
   */
  final List<LinkedDependencyBuilder> dependencies =
      <LinkedDependencyBuilder>[];

  /**
   * Map from the absolute URI of a dependent library to the index of the
   * corresponding entry in [dependencies].
   */
  final Map<String, int> uriToDependency = <String, int>{};

  /**
   * List of public namespaces corresponding to each entry in [dependencies].
   */
  final List<_Namespace> dependencyToPublicNamespace = <_Namespace>[];

  _Prelinker(this.definingUnitUri, this.definingUnit, this.getPart,
      this.getImport, this.getDeclaredVariable) {
    partCache[definingUnitUri] = definingUnit;
    importCache[definingUnitUri] = definingUnit.publicNamespace;
  }

  /**
   * Compute the public namespace for the library whose URI is reachable from
   * [definingUnit] via [absoluteUri], by aggregating together public namespace
   * information from all of its parts.
   */
  _Namespace aggregatePublicNamespace(String absoluteUri) {
    if (uriToDependency.containsKey(absoluteUri)) {
      return dependencyToPublicNamespace[uriToDependency[absoluteUri]];
    }
    assert(dependencies.length == dependencyToPublicNamespace.length);
    int dependency = dependencies.length;
    uriToDependency[absoluteUri] = dependency;
    List<String> unitUris = getUnitUris(absoluteUri);
    LinkedDependencyBuilder linkedDependency = new LinkedDependencyBuilder(
        uri: absoluteUri,
        parts: unitUris.skip(1).map((uri) => uri ?? '').toList());
    dependencies.add(linkedDependency);

    _Namespace aggregated = new _Namespace();

    for (int unitNum = 0; unitNum < unitUris.length; unitNum++) {
      String unitUri = unitUris[unitNum];
      UnlinkedPublicNamespace importedNamespace = getImportCached(unitUri);
      if (importedNamespace == null) {
        continue;
      }
      for (UnlinkedPublicName name in importedNamespace.names) {
        if (name.kind == ReferenceKind.classOrEnum) {
          _Namespace namespace = new _Namespace();
          name.members.forEach((executable) {
            namespace.add(
                executable.name,
                new _Meaning(
                    unitNum, executable.kind, 0, executable.numTypeParameters));
          });
          aggregated.add(
              name.name,
              new _ClassMeaning(
                  unitNum, dependency, name.numTypeParameters, namespace));
        } else {
          aggregated.add(
              name.name,
              new _Meaning(
                  unitNum, name.kind, dependency, name.numTypeParameters));
        }
      }
    }

    aggregated.rememberLibraryNames();

    dependencyToPublicNamespace.add(aggregated);
    return aggregated;
  }

  /**
   * Compute the export namespace for the library whose URI is reachable from
   * [definingUnit] via [absoluteUri], by aggregating together public namespace
   * information from the library and the transitive closure of its exports.
   */
  _Namespace computeExportNamespace(String absoluteUri) {
    Set<String> seenUris = new Set<String>();
    _Namespace chaseExports(String absoluteUri, NameFilter filter) {
      _Namespace exportedNamespace = aggregatePublicNamespace(absoluteUri);
      if (seenUris.add(absoluteUri)) {
        UnlinkedPublicNamespace publicNamespace = getImportCached(absoluteUri);
        if (publicNamespace != null) {
          for (UnlinkedExportPublic export in publicNamespace.exports) {
            String unlinkedExportUri =
                _selectUri(export.uri, export.configurations);
            String exportUri = resolveUri(absoluteUri, unlinkedExportUri);
            if (exportUri != null) {
              NameFilter newFilter = filter.merge(
                  new NameFilter.forUnlinkedCombinators(export.combinators));
              _Namespace exportNamespace = chaseExports(exportUri, newFilter);
              exportNamespace.forEach((String name, _Meaning meaning) {
                if (newFilter.accepts(name) &&
                    !exportedNamespace.definesLibraryName(name)) {
                  exportedNamespace.add(name, meaning);
                }
              });
            }
          }
        }
        seenUris.remove(absoluteUri);
      }
      return exportedNamespace;
    }

    return chaseExports(absoluteUri, NameFilter.identity);
  }

  /**
   * Extract all the names defined in [unit] (which is the [unitNum]th unit in
   * the library being prelinked) and store them in [privateNamespace].
   * Excludes names introduced by `import` statements.
   */
  void extractPrivateNames(UnlinkedUnit unit, int unitNum) {
    for (UnlinkedClass cls in unit.classes) {
      _Namespace namespace = new _Namespace();
      cls.fields.forEach((field) {
        if (field.isStatic && field.isConst) {
          namespace.add(field.name,
              new _Meaning(unitNum, ReferenceKind.propertyAccessor, 0, 0));
        }
      });
      cls.executables.forEach((executable) {
        ReferenceKind kind = null;
        if (executable.kind == UnlinkedExecutableKind.constructor) {
          kind = ReferenceKind.constructor;
        } else if (executable.kind == UnlinkedExecutableKind.functionOrMethod &&
            executable.isStatic) {
          kind = ReferenceKind.method;
        } else if (executable.kind == UnlinkedExecutableKind.getter &&
            executable.isStatic) {
          kind = ReferenceKind.propertyAccessor;
        }
        if (kind != null && executable.name.isNotEmpty) {
          namespace.add(executable.name,
              new _Meaning(unitNum, kind, 0, executable.typeParameters.length));
        }
      });
      privateNamespace.add(cls.name,
          new _ClassMeaning(unitNum, 0, cls.typeParameters.length, namespace));
    }
    for (UnlinkedEnum enm in unit.enums) {
      _Namespace namespace = new _Namespace();
      enm.values.forEach((UnlinkedEnumValue value) {
        namespace.add(value.name,
            new _Meaning(unitNum, ReferenceKind.propertyAccessor, 0, 0));
      });
      namespace.add('values',
          new _Meaning(unitNum, ReferenceKind.propertyAccessor, 0, 0));
      privateNamespace.add(
          enm.name, new _ClassMeaning(unitNum, 0, 0, namespace));
    }
    for (UnlinkedExecutable executable in unit.executables) {
      privateNamespace.add(
          executable.name,
          new _Meaning(
              unitNum,
              executable.kind == UnlinkedExecutableKind.functionOrMethod
                  ? ReferenceKind.topLevelFunction
                  : ReferenceKind.topLevelPropertyAccessor,
              0,
              executable.typeParameters.length));
    }
    for (UnlinkedTypedef typedef in unit.typedefs) {
      privateNamespace.add(
          typedef.name,
          new _Meaning(unitNum, ReferenceKind.typedef, 0,
              typedef.typeParameters.length));
    }
    for (UnlinkedVariable variable in unit.variables) {
      privateNamespace.add(variable.name,
          new _Meaning(unitNum, ReferenceKind.topLevelPropertyAccessor, 0, 0));
      if (!(variable.isConst || variable.isFinal)) {
        privateNamespace.add(
            variable.name + '=',
            new _Meaning(
                unitNum, ReferenceKind.topLevelPropertyAccessor, 0, 0));
      }
    }
  }

  /**
   * Filter the export namespace for the library whose URI is reachable the
   * given [absoluteUri], retaining only those names accepted by
   * [combinators], and store the resulting names in [result].  Names that
   * already exist in [result] are not overwritten.
   */
  void filterExportNamespace(String absoluteUri,
      List<UnlinkedCombinator> combinators, _Namespace result) {
    _Namespace exportNamespace = computeExportNamespace(absoluteUri);
    if (result == null) {
      // This can happen if the import prefix was shadowed by a local name, so
      // the imported symbols are inaccessible.
      return;
    }
    NameFilter filter = new NameFilter.forUnlinkedCombinators(combinators);
    exportNamespace.forEach((String name, _Meaning meaning) {
      if (filter.accepts(name) && !result.definesLibraryName(name)) {
        result.add(name, meaning);
      }
    });
  }

  /**
   * Wrapper around [getImport] that caches the return value in [importCache].
   */
  UnlinkedPublicNamespace getImportCached(String absoluteUri) {
    return importCache.putIfAbsent(absoluteUri, () => getImport(absoluteUri));
  }

  /**
   * Wrapper around [getPart] that caches the return value in [partCache] and
   * updates [importCache] appropriately.
   */
  UnlinkedUnit getPartCached(String absoluteUri) {
    return partCache.putIfAbsent(absoluteUri, () {
      UnlinkedUnit unit = getPart(absoluteUri);
      importCache[absoluteUri] = unit?.publicNamespace;
      return unit;
    });
  }

  /**
   * Compute the set of absolute URIs of all the compilation units in the
   * library whose URI is reachable from [definingUnit] via [absoluteUri].
   */
  List<String> getUnitUris(String absoluteUri) {
    List<String> result = <String>[absoluteUri];
    UnlinkedPublicNamespace publicNamespace = getImportCached(absoluteUri);
    if (publicNamespace != null) {
      result.addAll(publicNamespace.parts.map((String uri) {
        return resolveUri(absoluteUri, uri);
      }));
    }
    return result;
  }

  /**
   * Process a single `import` declaration in the library being prelinked.  The
   * return value is the index of the imported library in [dependencies].
   */
  int handleImport(UnlinkedImport import) {
    String unlinkedUri = import.isImplicit
        ? 'dart:core'
        : _selectUri(import.uri, import.configurations);
    String absoluteUri = resolveUri(definingUnitUri, unlinkedUri);

    _Namespace targetNamespace = null;
    if (import.prefixReference != 0) {
      // The name introduced by an import declaration can't have a prefix of
      // its own.
      assert(
          definingUnit.references[import.prefixReference].prefixReference == 0);
      String prefix = definingUnit.references[import.prefixReference].name;
      _Meaning prefixMeaning = privateNamespace[prefix];
      if (prefixMeaning is _PrefixMeaning) {
        targetNamespace = prefixMeaning.namespace;
      }
    } else {
      targetNamespace = privateNamespace;
    }
    filterExportNamespace(absoluteUri, import.combinators, targetNamespace);
    return uriToDependency[absoluteUri];
  }

  /**
   * Produce a [LinkedUnit] for the given [unit], by resolving every one of
   * its references.
   */
  LinkedUnitBuilder linkUnit(UnlinkedUnit unit) {
    if (unit == null) {
      return new LinkedUnitBuilder();
    }
    Map<int, _Namespace> prefixNamespaces = <int, _Namespace>{};
    List<LinkedReferenceBuilder> references = <LinkedReferenceBuilder>[];
    for (int i = 0; i < unit.references.length; i++) {
      UnlinkedReference reference = unit.references[i];
      _Namespace namespace;
      if (reference.prefixReference == 0) {
        namespace = privateNamespace;
      } else {
        // Prefix references must always point backward.
        assert(reference.prefixReference < i);
        namespace = prefixNamespaces[reference.prefixReference];
        // Expressions like 'a.b.c.d' cannot be prelinked.
        namespace ??= new _Namespace();
      }
      _Meaning meaning = namespace[reference.name];
      if (meaning != null) {
        if (meaning is _PrefixMeaning) {
          prefixNamespaces[i] = meaning.namespace;
        } else if (meaning is _ClassMeaning) {
          prefixNamespaces[i] = meaning.namespace;
        }
        references.add(meaning.encodeReference());
      } else {
        references
            .add(new LinkedReferenceBuilder(kind: ReferenceKind.unresolved));
      }
    }
    return new LinkedUnitBuilder(references: references);
  }

  /**
   * Form the [LinkedLibrary] for the [definingUnit] that was passed to the
   * constructor.
   */
  LinkedLibraryBuilder prelink() {
    aggregatePublicNamespace(definingUnitUri);

    // Gather up the unlinked summaries for all the compilation units in the
    // library.
    List<String> unitUris = getUnitUris(definingUnitUri);
    List<UnlinkedUnit> units = unitUris.map(getPartCached).toList();

    // Create the private namespace for the library by gathering all the names
    // defined in its compilation units.
    for (int unitNum = 0; unitNum < units.length; unitNum++) {
      UnlinkedUnit unit = units[unitNum];
      if (unit != null) {
        extractPrivateNames(unit, unitNum);
      }
    }

    // Fill in exported names.  This must be done before filling in prefixes
    // defined in import declarations, because prefixes shouldn't shadow
    // exports.
    List<LinkedExportNameBuilder> exportNames = <LinkedExportNameBuilder>[];
    computeExportNamespace(definingUnitUri)
        .forEach((String name, _Meaning meaning) {
      if (!privateNamespace.definesName(name)) {
        exportNames.add(meaning.encodeExportName(name));
      }
    });

    // Fill in prefixes defined in import declarations.
    for (UnlinkedImport import in units[0].imports) {
      if (import.prefixReference != 0) {
        String name = units[0].references[import.prefixReference].name;
        if (!privateNamespace.definesName(name)) {
          privateNamespace.add(name, new _PrefixMeaning());
        }
      }
    }

    // All the names defined so far are library local, they take precedence
    // over anything imported from other libraries.
    privateNamespace.rememberLibraryNames();

    // Fill in imported and exported names.
    List<int> importDependencies =
        definingUnit.imports.map(handleImport).toList();
    List<int> exportDependencies = definingUnit.publicNamespace.exports
        .map((UnlinkedExportPublic exp) {
          String unlinkedUri = _selectUri(exp.uri, exp.configurations);
          String absoluteUri = resolveUri(definingUnitUri, unlinkedUri);
          return uriToDependency[absoluteUri];
        })
        .where((dependency) => dependency != null)
        .toList();

    // Link each compilation unit.
    List<LinkedUnitBuilder> linkedUnits = units.map(linkUnit).toList();

    return new LinkedLibraryBuilder(
        units: linkedUnits,
        dependencies: dependencies,
        importDependencies: importDependencies,
        exportDependencies: exportDependencies,
        exportNames: exportNames,
        numPrelinkedDependencies: dependencies.length);
  }

  /**
   * Resolve [relativeUri] relative to [containingUri].  Return `null` if
   * [relativeUri] is invalid or empty, so cannot be resolved.
   */
  String resolveUri(String containingUri, String relativeUri) {
    if (relativeUri == '') {
      return null;
    }
    try {
      Uri containingUriObj = Uri.parse(containingUri);
      Uri relativeUriObj = Uri.parse(relativeUri);
      return resolveRelativeUri(containingUriObj, relativeUriObj).toString();
    } on FormatException {
      return null;
    }
  }

  /**
   * Return the URI of the first configuration from the given [configurations]
   * which condition is satisfied, or the [defaultUri].
   */
  String _selectUri(
      String defaultUri, List<UnlinkedConfiguration> configurations) {
    for (UnlinkedConfiguration configuration in configurations) {
      if (getDeclaredVariable(configuration.name) == configuration.value) {
        return configuration.uri;
      }
    }
    return defaultUri;
  }
}
