// 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:front_end/src/builder/property_builder.dart';
import 'package:kernel/ast.dart' show LibraryDependency;

import '../base/combinator.dart';
import '../base/lookup_result.dart';
import '../base/messages.dart';
import '../base/name_space.dart';
import '../base/scope.dart';
import '../base/uri_offset.dart';
import '../kernel/load_library_builder.dart' show LoadLibraryBuilder;
import '../kernel/utils.dart';
import '../source/source_library_builder.dart';
import 'builder.dart';
import 'compilation_unit.dart';
import 'declaration_builders.dart';

class PrefixBuilder extends NamedBuilderImpl implements LookupResult {
  @override
  final String name;

  final ComputedMutableNameSpace _prefixNameSpace =
      new ComputedMutableNameSpace();

  late final LookupScope _prefixScope =
      new NameSpaceLookupScope(_prefixNameSpace, ScopeKind.library);

  @override
  final SourceLibraryBuilder parent;

  final bool deferred;

  @override
  final Uri fileUri;

  @override
  final int fileOffset;

  final LoadLibraryBuilder? loadLibraryBuilder;

  final bool isWildcard;

  PrefixBuilder(this.name, this.deferred, this.parent, this.loadLibraryBuilder,
      {required this.fileUri,
      required int prefixOffset,
      required int importOffset})
      : fileOffset = prefixOffset,
        isWildcard = name == '_' {
    assert(deferred == (loadLibraryBuilder != null),
        "LoadLibraryBuilder must be provided iff prefix is deferred.");
    if (loadLibraryBuilder != null) {
      addToPrefixScope(loadLibraryBuilder!.name, loadLibraryBuilder!,
          importOffset: importOffset, prefixOffset: prefixOffset);
    }
  }

  LookupScope get prefixScope => _prefixScope;

  void forEachExtension(void Function(ExtensionBuilder) f) {
    _prefixNameSpace.forEachLocalExtension(f);
  }

  LibraryDependency? get dependency => loadLibraryBuilder?.importDependency;

  /// Lookup a member with [name] in the export scope.
  LookupResult? lookup(String name, int charOffset, Uri fileUri) {
    return _prefixScope.lookup(name, charOffset, fileUri);
  }

  void addToPrefixScope(String name, NamedBuilder member,
      {required int importOffset, required int prefixOffset}) {
    if (deferred && member is ExtensionBuilder) {
      parent.addProblem(templateDeferredExtensionImport.withArguments(name),
          importOffset, noLength, fileUri);
    }

    bool isSetter = isMappedAsSetter(member);

    LookupResult? existingResult = _prefixNameSpace.lookupLocalMember(name);
    NamedBuilder? existing =
        isSetter ? existingResult?.setable : existingResult?.getable;
    if (existing != null) {
      NamedBuilder result = computeAmbiguousDeclarationForImport(
          parent, name, existing, member,
          uriOffset: new UriOffset(fileUri, prefixOffset));
      _prefixNameSpace.replaceLocalMember(name, result, setter: isSetter);
    } else {
      _prefixNameSpace.addLocalMember(name, member, setter: isSetter);
    }
    if (member is ExtensionBuilder) {
      _prefixNameSpace.addExtension(member);
    }
  }

  @override
  // Coverage-ignore(suite): Not run.
  String get fullNameForErrors => name;

  @override
  NamedBuilder get getable => this;

  @override
  NamedBuilder? get setable => null;
}

class PrefixFragment {
  final String name;
  final SourceCompilationUnit importer;
  final CompilationUnit? imported;
  final List<CombinatorBuilder>? combinators;
  final bool deferred;
  final Uri fileUri;
  final int importOffset;
  final int prefixOffset;

  PrefixBuilder? _builder;

  PrefixFragment({
    required this.name,
    required this.importer,
    required this.imported,
    required this.combinators,
    required this.deferred,
    required this.fileUri,
    required this.importOffset,
    required this.prefixOffset,
  });

  PrefixBuilder createPrefixBuilder() {
    LoadLibraryBuilder? loadLibraryBuilder;
    if (deferred) {
      loadLibraryBuilder = new LoadLibraryBuilder(
          importer.libraryBuilder,
          prefixOffset,
          imported!,
          name,
          importOffset,
          toCombinators(combinators));
    }

    return builder = new PrefixBuilder(
        name, deferred, importer.libraryBuilder, loadLibraryBuilder,
        fileUri: fileUri,
        prefixOffset: prefixOffset,
        importOffset: importOffset);
  }

  PrefixBuilder get builder {
    assert(_builder != null, "Builder has not been computed for $this.");
    return _builder!;
  }

  void set builder(PrefixBuilder value) {
    assert(_builder == null, "Builder has already been computed for $this.");
    _builder = value;
  }

  @override
  String toString() => '$runtimeType($name,$fileUri,$importOffset)';
}
