// Copyright (c) 2025, 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:kernel/ast.dart';

import '../builder/builder.dart';
import '../builder/declaration_builders.dart';
import '../builder/member_builder.dart';
import '../codes/cfe_codes.dart';
import 'compiler_context.dart';

abstract class LookupResult {
  /// The [NamedBuilder] used for reading this entity, if any.
  NamedBuilder? get getable;

  /// The [NamedBuilder] used for writing to this entity, if any.
  NamedBuilder? get setable;

  /// Returns `true` if the result is invalid.
  ///
  /// For instance because of duplicate declaration or because of an invalid
  /// scope origin.
  bool get isInvalidLookup;

  static LocatedMessage createDuplicateMessage(
    LookupResult lookupResult, {
    DeclarationBuilder? enclosingDeclaration,
    required String name,
    required Uri fileUri,
    required int fileOffset,
    required int length,
  }) {
    if (name.isEmpty) {
      if (enclosingDeclaration != null) {
        name = enclosingDeclaration.name;
      } else {
        name = 'new';
      }
      length = noLength;
    }
    Message message = codeDuplicatedDeclarationUse.withArgumentsOld(name);
    return message.withLocation(fileUri, fileOffset, length);
  }

  static InvalidExpression createDuplicateExpression(
    LookupResult lookupResult, {
    required CompilerContext context,
    DeclarationBuilder? enclosingDeclaration,
    required String name,
    required Uri fileUri,
    required int fileOffset,
    required int length,
  }) {
    String text = context
        .format(
          createDuplicateMessage(
            lookupResult,
            enclosingDeclaration: enclosingDeclaration,
            name: name,
            fileUri: fileUri,
            fileOffset: fileOffset,
            length: length,
          ),
          CfeSeverity.error,
        )
        .plain;
    return new InvalidExpression(text)..fileOffset = fileOffset;
  }

  static LookupResult? createResult(
    NamedBuilder? getable,
    NamedBuilder? setable,
  ) {
    return _fromBuilders(getable, setable, assertNoGetterSetterConflict: false);
  }

  static LookupResult? _fromBuilders(
    NamedBuilder? getable,
    NamedBuilder? setable, {
    required bool assertNoGetterSetterConflict,
  }) {
    if (getable is LookupResult) {
      LookupResult lookupResult = getable as LookupResult;
      if (setable == getable) {
        return lookupResult;
      } else if (setable == null) {
        return lookupResult;
      } else {
        assert(
          getable != setable,
          "Unexpected getable $getable and setable $setable.",
        );
        assert(
          !assertNoGetterSetterConflict ||
              // Coverage-ignore(suite): Not run.
              lookupResult.setable == null,
          "Unexpected setable ${lookupResult.setable} from "
          "getable $getable and setable $setable.",
        );
        return new GetableSetableResult(getable!, setable);
      }
    } else if (setable is LookupResult) {
      // Coverage-ignore-block(suite): Not run.
      LookupResult lookupResult = setable as LookupResult;
      if (getable == null) {
        return lookupResult;
      } else {
        assert(
          getable != setable,
          "Unexpected getable $getable and setable $setable.",
        );
        assert(
          !assertNoGetterSetterConflict || lookupResult.getable == null,
          "Unexpected getable ${lookupResult.getable} from "
          "setable $setable and getable $getable.",
        );
        return new GetableSetableResult(getable, setable!);
      }
    } else {
      // Coverage-ignore-block(suite): Not run.
      if (getable != null && setable != null) {
        return new GetableSetableResult(getable, setable);
      } else if (getable != null) {
        return new GetableResult(getable);
      } else if (setable != null) {
        return new SetableResult(setable);
      } else {
        return null;
      }
    }
  }
}

abstract class InvalidLookupResult implements LookupResult {
  factory InvalidLookupResult(LocatedMessage message) =
      _InvalidLookupResultImpl;

  LocatedMessage get message;
}

// Coverage-ignore(suite): Not run.
class _InvalidLookupResultImpl implements InvalidLookupResult {
  @override
  final LocatedMessage message;

  _InvalidLookupResultImpl(this.message);

  @override
  bool get isInvalidLookup => true;

  @override
  NamedBuilder? get getable => null;

  @override
  NamedBuilder? get setable => null;
}

abstract class MemberLookupResult implements LookupResult {
  /// The [MemberBuilder] used for reading this entity, if any.
  @override
  MemberBuilder? get getable;

  /// The [MemberBuilder] used for writing to this entity, if any.
  @override
  MemberBuilder? get setable;

  /// Return `true` if this [MemberBuilder]s of this lookup result are accessed
  /// statically.
  bool get isStatic;
}

class InvalidMemberLookupResult
    implements InvalidLookupResult, MemberLookupResult {
  @override
  final LocatedMessage message;

  InvalidMemberLookupResult(this.message);

  @override
  bool get isInvalidLookup => true;

  @override
  // Coverage-ignore(suite): Not run.
  MemberBuilder? get getable => null;

  @override
  // Coverage-ignore(suite): Not run.
  MemberBuilder? get setable => null;

  @override
  // Coverage-ignore(suite): Not run.
  bool get isStatic => true;
}

class GetableResult with LookupResultMixin implements LookupResult {
  @override
  final NamedBuilder getable;

  GetableResult(this.getable);

  @override
  NamedBuilder? get setable => null;
}

// Coverage-ignore(suite): Not run.
class SetableResult with LookupResultMixin implements LookupResult {
  @override
  final NamedBuilder setable;

  SetableResult(this.setable);

  @override
  NamedBuilder? get getable => null;
}

class GetableSetableResult with LookupResultMixin implements LookupResult {
  @override
  final NamedBuilder getable;

  @override
  final NamedBuilder setable;

  GetableSetableResult(this.getable, this.setable);
}

class SetableMemberResult with LookupResultMixin implements MemberLookupResult {
  @override
  final MemberBuilder setable;

  @override
  final bool isStatic;

  SetableMemberResult(this.setable, {required this.isStatic});

  @override
  MemberBuilder? get getable => null;
}

class GetableSetableMemberResult
    with LookupResultMixin
    implements MemberLookupResult {
  @override
  final MemberBuilder getable;

  @override
  final MemberBuilder setable;

  @override
  final bool isStatic;

  GetableSetableMemberResult(
    this.getable,
    this.setable, {
    required this.isStatic,
  });
}

mixin LookupResultMixin implements LookupResult {
  @override
  bool get isInvalidLookup =>
      (getable?.isDuplicate ?? false) || (setable?.isDuplicate ?? false);
}

class DuplicateMemberLookupResult implements MemberLookupResult {
  final List<MemberBuilder> declarations;

  DuplicateMemberLookupResult(this.declarations);

  @override
  MemberBuilder? get getable => null;

  @override
  bool get isInvalidLookup => true;

  @override
  MemberBuilder? get setable => null;

  /// Return `true` if this [MemberBuilder]s of this lookup result are accessed
  /// statically.
  ///
  /// Since this lookup can contain both static and non-static members, we
  /// return `true` so that it will not be filtered in static member lookup.
  @override
  bool get isStatic => true;
}
