// Copyright (c) 2020, 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.

/// Data structure representing a part of a type.  When a fix has multiple
/// reasons (due to a complex type having different nullabilities at different
/// locations), this data structure allows us to tell which part of the type
/// is associated with each reason.
abstract class FixReasonTarget {
  /// Fix reason target representing the full type, rather than a part of it.
  static const FixReasonTarget root = _FixReasonTarget_Root();

  const FixReasonTarget._();

  /// Gets a fix reason target representing the type's return type.
  FixReasonTarget get returnType => _FixReasonTarget_ReturnType(this);

  /// Returns a description of the fix reason target that's suitable for
  /// appending to a description of a nullability trace.
  ///
  /// For example, `root.returnType.suffix` returns ` for return type`.  This
  /// can be attached to a string like `nullability reason` to form
  /// `nullability reason for return type`.
  String get suffix => _describe('for');

  /// Gets a fix reason target representing the type's yielded type.  This
  /// represents the type argument of `Future` or `FutureOr`, or in the case
  /// where `await` is applied to a non-future type, the type itself.
  FixReasonTarget get yieldedType => _FixReasonTarget_YieldedType(this);

  /// Gets a fix reason target representing one of the type's named parameters.
  FixReasonTarget namedParameter(String name) =>
      _FixReasonTarget_NamedParameter(this, name);

  /// Gets a fix reason target representing one of the type's positional
  /// parameters.
  FixReasonTarget positionalParameter(int i) =>
      _FixReasonTarget_PositionalParameter(this, i);

  /// Gets a fix reason target representing one of the type's type arguments.
  FixReasonTarget typeArgument(int i) => _FixReasonTarget_TypeArgument(this, i);

  String _describe(String preposition);
}

/// Fix reason target representing a named parameter of a function type.
class _FixReasonTarget_NamedParameter extends _FixReasonTarget_Part {
  final String name;

  _FixReasonTarget_NamedParameter(super.inner, this.name);

  @override
  int get hashCode => Object.hash(2, inner, name);

  @override
  bool operator ==(Object other) =>
      other is _FixReasonTarget_NamedParameter &&
      inner == other.inner &&
      name == other.name;

  @override
  String _describe(String preposition) =>
      ' $preposition parameter $name${inner._describe('of')}';
}

/// Fix reason target representing a type that forms part of a larger type (e.g.
/// the `int` part of `List<int>`).
abstract class _FixReasonTarget_Part extends FixReasonTarget {
  final FixReasonTarget inner;

  _FixReasonTarget_Part(this.inner) : super._();
}

/// Fix reason target representing a positional parameter of a function type.
class _FixReasonTarget_PositionalParameter extends _FixReasonTarget_Part {
  final int index;

  _FixReasonTarget_PositionalParameter(super.inner, this.index);

  @override
  int get hashCode => Object.hash(1, inner, index);

  @override
  bool operator ==(Object other) =>
      other is _FixReasonTarget_PositionalParameter &&
      inner == other.inner &&
      index == other.index;

  @override
  String _describe(String preposition) =>
      ' $preposition parameter $index${inner._describe('of')}';
}

/// Fix reason target representing the return type of a function type.
class _FixReasonTarget_ReturnType extends _FixReasonTarget_Part {
  _FixReasonTarget_ReturnType(super.inner);

  @override
  int get hashCode => Object.hash(3, inner);

  @override
  bool operator ==(Object other) =>
      other is _FixReasonTarget_ReturnType && inner == other.inner;

  @override
  String _describe(String preposition) =>
      ' $preposition return type${inner._describe('of')}';
}

/// Fix reason target representing the root of the type in question.
class _FixReasonTarget_Root extends FixReasonTarget {
  const _FixReasonTarget_Root() : super._();

  @override
  int get hashCode => 0;

  @override
  bool operator ==(Object other) => other is _FixReasonTarget_Root;

  @override
  String _describe(String preposition) => '';
}

/// Fix reason target representing a type argument of an interface type.
class _FixReasonTarget_TypeArgument extends _FixReasonTarget_Part {
  final int index;

  _FixReasonTarget_TypeArgument(super.inner, this.index);

  @override
  int get hashCode => Object.hash(5, inner, index);

  @override
  bool operator ==(Object other) =>
      other is _FixReasonTarget_TypeArgument &&
      inner == other.inner &&
      index == other.index;

  @override
  String _describe(String preposition) =>
      ' $preposition type argument $index${inner._describe('of')}';
}

/// Fix reason target representing the type argument of `Future` or `FutureOr`,
/// or in the case where `await` is applied to a non-future type, the type
/// itself.
///
/// This allows the migration tool to describe a type correspondence that exists
/// in a subtype check involving `FutureOr`, for example if the user tries to
/// assign `List<int?>` to `FutureOr<List<int*>>`, then the migration tool
/// determines that it needs to change `*` into `?`.  To make this determination
/// it has to form a correspondence between the type argument of the source type
/// and the type argument of the type argument of the destination type.  To
/// explain to the user which part of the two types is involved in the
/// correspondence, we need an ambiguous way of referring to either "type
/// argument of type argument of" or simply "type argument".  The solution is to
/// describe the fix reason target as "type argument of yielded type".
class _FixReasonTarget_YieldedType extends _FixReasonTarget_Part {
  _FixReasonTarget_YieldedType(super.inner);

  @override
  int get hashCode => Object.hash(4, inner);

  @override
  bool operator ==(Object other) =>
      other is _FixReasonTarget_YieldedType && inner == other.inner;

  @override
  String _describe(String preposition) =>
      ' $preposition yielded type${inner._describe('from')}';
}
