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

import '../ast.dart';
import 'text_util.dart';

/// AST printer strategy used by default in `Node.toString`.
///
/// Don't use this for testing. Instead use [astTextStrategyForTesting] or
/// make an explicit strategy for the test to avoid test dependency on the
/// `Node.toString` implementation.
const AstTextStrategy defaultAstTextStrategy = const AstTextStrategy();

/// Strategy used for printing AST nodes.
///
/// This is used to avoid dependency on the `Node.toString` implementations
/// in testing.
const AstTextStrategy astTextStrategyForTesting = const AstTextStrategy(
  includeLibraryNamesInMembers: true,
  includeLibraryNamesInTypes: true,
  includeAuxiliaryProperties: false,
  useMultiline: false,
);

class AstTextStrategy {
  /// If `true`, references to classes and typedefs in types are prefixed by the
  /// name of their enclosing library.
  final bool includeLibraryNamesInTypes;

  /// If `true`, references to members, classes and typedefs are prefixed by the
  /// name of their enclosing library.
  final bool includeLibraryNamesInMembers;

  /// If `true`, auxiliary node properties are on include in the textual
  /// representation.
  final bool includeAuxiliaryProperties;

  /// If `true`, only [Nullability.nullable] is shown on types.
  final bool showNullableOnly;

  /// If `true`, type parameter names qualified by the name of the declaring
  /// class or function.
  final bool useQualifiedTypeParameterNames;

  /// If `true`, type parameter names qualified also by local functions
  /// (if named).
  final bool useQualifiedTypeParameterNamesRecurseOnNamedLocalFunctions;

  /// If `true`, newlines are used to separate statements.
  final bool useMultiline;

  /// If [useMultiline] is `true`, [indentation] is used for indentation.
  final String indentation;

  /// If non-null, a maximum of [maxStatementDepth] nested statements are
  /// printed. If exceeded, '...' is printed instead.
  final int? maxStatementDepth;

  /// If non-null, a maximum of [maxStatementsLength] statements are printed
  /// within the same block.
  final int? maxStatementsLength;

  /// If non-null, a maximum of [maxExpressionDepth] nested expression are
  /// printed. If exceeded, '...' is printed instead.
  final int? maxExpressionDepth;

  /// If non-null, a maximum of [maxExpressionsLength] expression are printed
  /// within the same list of expressions, for instance in list/set literals.
  /// If exceeded, '...' is printed instead.
  final int? maxExpressionsLength;

  /// If non-null, a maximum of [maxConstantDepth] nested constants are
  /// printed. If exceeded, '...' is printed instead.
  final int? maxConstantDepth;

  const new({
    this.includeLibraryNamesInTypes = false,
    this.includeLibraryNamesInMembers = false,
    this.includeAuxiliaryProperties = false,
    this.showNullableOnly = false,
    this.useQualifiedTypeParameterNames = true,
    this.useQualifiedTypeParameterNamesRecurseOnNamedLocalFunctions = false,
    this.useMultiline = true,
    this.indentation = '  ',
    this.maxStatementDepth = 50,
    this.maxStatementsLength = null,
    this.maxExpressionDepth = 50,
    this.maxExpressionsLength = null,
    this.maxConstantDepth = 10,
  });
}

class AstPrinter {
  final AstTextStrategy _strategy;
  final StringBuffer _sb = new StringBuffer();
  int _statementLevel = 0;
  int _expressionLevel = 0;
  int _constantLevel = 0;
  int _indentationLevel = 0;
  late final Map<LabeledStatement, String> _labelNames = {};
  late final Map<VariableBase, String> _variableNames = {};

  new(this._strategy);

  bool get includeAuxiliaryProperties => _strategy.includeAuxiliaryProperties;

  void incIndentation() {
    _indentationLevel++;
  }

  void decIndentation() {
    _indentationLevel--;
  }

  void write(String value) {
    _sb.write(value);
  }

  void writeClassName(Reference? reference, {bool forType = false}) {
    _sb.write(
      qualifiedClassNameToStringByReference(
        reference,
        includeLibraryName: forType
            ? _strategy.includeLibraryNamesInTypes
            : _strategy.includeLibraryNamesInMembers,
      ),
    );
  }

  void writeTypedefName(Reference? reference) {
    _sb.write(
      qualifiedTypedefNameToStringByReference(
        reference,
        includeLibraryName: _strategy.includeLibraryNamesInTypes,
      ),
    );
  }

  void writeExtensionName(Reference? reference) {
    _sb.write(
      qualifiedExtensionNameToStringByReference(
        reference,
        includeLibraryName: _strategy.includeLibraryNamesInMembers,
      ),
    );
  }

  void writeExtensionTypeDeclarationName(Reference? reference) {
    _sb.write(
      qualifiedExtensionTypeDeclarationNameToStringByReference(
        reference,
        includeLibraryName: _strategy.includeLibraryNamesInMembers,
      ),
    );
  }

  void writeQualifiedCanonicalNameToString(CanonicalName canonicalName) {
    _sb.write(
      qualifiedCanonicalNameToString(
        canonicalName,
        includeLibraryName: _strategy.includeLibraryNamesInMembers,
        includeLibraryNamesInTypes: _strategy.includeLibraryNamesInTypes,
      ),
    );
  }

  void writeMemberName(Reference? reference) {
    _sb.write(
      qualifiedMemberNameToStringByReference(
        reference,
        includeLibraryName: _strategy.includeLibraryNamesInMembers,
      ),
    );
  }

  void writeInterfaceMemberName(Reference? reference, Name? name) {
    if (name != null && (reference == null || reference.node == null)) {
      writeName(name);
    } else {
      write('{');
      _sb.write(
        qualifiedMemberNameToStringByReference(
          reference,
          includeLibraryName: _strategy.includeLibraryNamesInMembers,
        ),
      );
      write('}');
    }
  }

  void writeLibraryReference(Reference reference) {
    _sb.write(libraryReferenceToString(reference));
  }

  void writeName(Name? name) {
    _sb.write(
      nameToString(
        name,
        includeLibraryName: _strategy.includeLibraryNamesInMembers,
      ),
    );
  }

  void writeNamedType(NamedType node) {
    node.toTextInternal(this);
  }

  void writeTypeParameterName(TypeParameter parameter) {
    _sb.write(
      _strategy.useQualifiedTypeParameterNames
          ? qualifiedTypeParameterNameToString(
              parameter,
              includeLibraryName: _strategy.includeLibraryNamesInTypes,
              recurseOnLocalFunction: _strategy
                  .useQualifiedTypeParameterNamesRecurseOnNamedLocalFunctions,
            )
          : typeParameterNameToString(parameter),
    );
  }

  void writeStructuralParameterName(StructuralParameter parameter) {
    _sb.write(
      _strategy.useQualifiedTypeParameterNames
          ? qualifiedStructuralParameterNameToString(
              parameter,
              includeLibraryName: _strategy.includeLibraryNamesInTypes,
            )
          : structuralParameterNameToString(parameter),
    );
  }

  void newLine() {
    if (_strategy.useMultiline) {
      _sb.writeln();
      _sb.write(_strategy.indentation * _indentationLevel);
    } else {
      _sb.write(' ');
    }
  }

  String getLabelName(LabeledStatement node) {
    return _labelNames[node] ??= 'label${_labelNames.length}';
  }

  String getVariableName(VariableBase node) {
    switch (node) {
      case NamedParameter(parameterName: var name):
      case PositionalParameter(cosmeticName: var name?):
      case TypeVariable(cosmeticName: var name?):
      case LocalVariable(cosmeticName: var name?):
      case LateVariable(cosmeticName: var name?):
      case ConstVariable(cosmeticName: var name?):
      case LocalFunctionVariable(cosmeticName: var name?):
        return name;
      case ThisVariable():
        return 'this';
      case PositionalParameter(cosmeticName: null):
      case TypeVariable(cosmeticName: null):
      case LocalVariable(cosmeticName: null):
      case LateVariable(cosmeticName: null):
      case ConstVariable(cosmeticName: null):
      case LocalFunctionVariable(cosmeticName: null):
      case SyntheticVariable():
        return _variableNames[node] ??= '#${_variableNames.length}';
      case CatchVariable(catchVariableName: var name):
        return name;
    }
  }

  String getSwitchCaseName(SwitchCase node) {
    if (node.isDefault) {
      return '"default:"';
    } else {
      return '"case ${node.expressions.first.toText(_strategy)}:"';
    }
  }

  void writeStatement(Statement node) {
    int oldStatementLevel = _statementLevel;
    _statementLevel++;
    if (_strategy.maxStatementDepth != null &&
        _statementLevel > _strategy.maxStatementDepth!) {
      _sb.write('...');
    } else {
      node.toTextInternal(this);
    }
    _statementLevel = oldStatementLevel;
  }

  void writeExpression(Expression node, {int? minimumPrecedence}) {
    int oldExpressionLevel = _expressionLevel;
    _expressionLevel++;
    if (_strategy.maxExpressionDepth != null &&
        _expressionLevel > _strategy.maxExpressionDepth!) {
      _sb.write('...');
    } else {
      bool needsParentheses =
          minimumPrecedence != null && node.precedence < minimumPrecedence;
      if (needsParentheses) {
        _sb.write('(');
      }
      node.toTextInternal(this);
      if (needsParentheses) {
        _sb.write(')');
      }
    }
    _expressionLevel = oldExpressionLevel;
  }

  void writeNamedExpression(NamedExpression node) {
    node.toTextInternal(this);
  }

  void writeCatch(Catch node) {
    node.toTextInternal(this);
  }

  void writeSwitchCase(SwitchCase node) {
    node.toTextInternal(this);
  }

  void writeType(DartType node) {
    node.toTextInternal(this);
  }

  void writeNullability(Nullability nullability) {
    if (!_strategy.showNullableOnly || nullability == Nullability.nullable) {
      write(nullabilityToString(nullability));
    }
  }

  void writeConstant(Constant node) {
    int oldConstantLevel = _constantLevel;
    _constantLevel++;
    if (_strategy.maxConstantDepth != null &&
        _constantLevel > _strategy.maxConstantDepth!) {
      _sb.write('...');
    } else {
      node.toTextInternal(this);
    }
    _constantLevel = oldConstantLevel;
  }

  void writeMapEntry(MapLiteralEntry node) {
    node.toTextInternal(this);
  }

  /// Writes [types] to the printer buffer separated by ', '.
  void writeTypes(List<DartType> types) {
    for (int index = 0; index < types.length; index++) {
      if (index > 0) {
        _sb.write(', ');
      }
      writeType(types[index]);
    }
  }

  /// If [types] is non-empty, writes [types] to the printer buffer delimited by
  /// '<' and '>', and separated by ', '.
  void writeTypeArguments(List<DartType> types) {
    if (types.isNotEmpty) {
      _sb.write('<');
      writeTypes(types);
      _sb.write('>');
    }
  }

  /// If [typeParameters] is non-empty, writes [typeParameters] to the printer
  /// buffer delimited by '<' and '>', and separated by ', '.
  ///
  /// The bound of a type parameter is included, as 'T extends Bound', if the
  /// bound is neither `Object?` nor `Object*`.
  void writeTypeParameters(List<TypeParameter> typeParameters) {
    if (typeParameters.isNotEmpty) {
      _sb.write("<");
      String comma = "";
      for (TypeParameter typeParameter in typeParameters) {
        _sb.write(comma);
        _sb.write(typeParameter.name);
        DartType bound = typeParameter.bound;

        bool isTopObject(DartType type) {
          if (type is InterfaceType &&
              type.classReference.node != null &&
              type.classNode.name == 'Object') {
            Uri uri = type.classNode.enclosingLibrary.importUri;
            return uri.isScheme('dart') &&
                uri.path == 'core' &&
                type.nullability == Nullability.nullable;
          }
          return false;
        }

        if (!isTopObject(bound) || isTopObject(typeParameter.defaultType)) {
          // Include explicit bounds only.
          _sb.write(' extends ');
          writeType(bound);
        }
        comma = ", ";
      }
      _sb.write(">");
    }
  }

  /// If [typeParameters] is non-empty, writes [typeParameters] to the printer
  /// buffer delimited by '<' and '>', and separated by ', '.
  ///
  /// The bound of a type parameter is included, as 'T extends Bound', if the
  /// bound is neither `Object?` nor `Object*`.
  void writeStructuralParameters(List<StructuralParameter> typeParameters) {
    if (typeParameters.isNotEmpty) {
      _sb.write("<");
      String comma = "";
      for (StructuralParameter typeParameter in typeParameters) {
        _sb.write(comma);
        _sb.write(typeParameter.name);
        DartType bound = typeParameter.bound;

        bool isTopObject(DartType type) {
          if (type is InterfaceType &&
              type.classReference.node != null &&
              type.classNode.name == 'Object') {
            Uri uri = type.classNode.enclosingLibrary.importUri;
            return uri.isScheme('dart') &&
                uri.path == 'core' &&
                type.nullability == Nullability.nullable;
          }
          return false;
        }

        if (!isTopObject(bound) || isTopObject(typeParameter.defaultType)) {
          // Include explicit bounds only.
          _sb.write(' extends ');
          writeType(bound);
        }
        comma = ", ";
      }
      _sb.write(">");
    }
  }

  /// Writes [expressions] to the printer buffer separated by ', '.
  void writeExpressions(List<Expression> expressions) {
    if (expressions.isNotEmpty &&
        _strategy.maxExpressionDepth != null &&
        _expressionLevel + 1 > _strategy.maxExpressionDepth!) {
      // The maximum expression depth will be exceeded for all [expressions].
      // Print the list as one occurrence '...' instead one per expression.
      _sb.write('...');
    } else if (_strategy.maxExpressionsLength != null &&
        expressions.length > _strategy.maxExpressionsLength!) {
      _sb.write('...');
    } else {
      for (int index = 0; index < expressions.length; index++) {
        if (index > 0) {
          _sb.write(', ');
        }
        writeExpression(expressions[index]);
      }
    }
  }

  /// Writes [statements] to the printer buffer delimited by '{' and '}'.
  ///
  /// If using a multiline strategy, the statements printed on separate lines
  /// that are indented one level.
  void writeBlock(List<Statement> statements) {
    if (statements.isEmpty) {
      write('{}');
    } else {
      write('{');
      incIndentation();
      writeStatements(statements);
      decIndentation();
      newLine();
      write('}');
    }
  }

  /// Writes [statements] to the printer buffer.
  ///
  /// If using a multiline strategy, the statements printed on separate lines
  /// that are indented one level.
  void writeStatements(List<Statement> statements) {
    if (statements.isNotEmpty &&
        _strategy.maxStatementDepth != null &&
        _statementLevel + 1 > _strategy.maxStatementDepth!) {
      // The maximum statement depth will be exceeded for all [statements].
      // Print the list as one occurrence '...' instead one per statement.
      _sb.write(' ...');
    } else if (_strategy.maxStatementsLength != null &&
        statements.length > _strategy.maxStatementsLength!) {
      _sb.write(' ...');
    } else {
      for (Statement statement in statements) {
        newLine();
        writeStatement(statement);
      }
    }
  }

  /// Writes arguments [node] to the printer buffer.
  ///
  /// If [includeTypeArguments] is `true` type arguments in [node] are included.
  /// Otherwise only the positional and named arguments are included.
  void writeArguments(Arguments node, {bool includeTypeArguments = true}) {
    node.toTextInternal(this, includeTypeArguments: includeTypeArguments);
  }

  /// Writes the [VariableDeclaration] [node] to the printer buffer.
  ///
  /// If [includeModifiersAndType] is `true`, the declaration is prefixed by
  /// the modifiers and declared type of the variable. Otherwise only the
  /// name and the initializer, if present, are included.
  ///
  /// If [isLate] and [type] are provided, these values are used instead of
  /// the corresponding properties on [node].
  void writeVariableDeclaration(
    VariableDeclaration node, {
    bool includeModifiersAndType = true,
    bool? isLate,
    DartType? type,
    bool includeInitializer = true,
    bool isImplicitlyTyped = false,
  }) {
    writeVariableInitialization(
      node.variable,
      includeModifiersAndType: includeModifiersAndType,
      isLate: isLate,
      type: type,
      includeInitializer: includeInitializer,
      isImplicitlyTyped: isImplicitlyTyped,
    );
  }

  /// Writes the [VariableInitialization] [node] to the printer buffer.
  ///
  /// If [includeModifiersAndType] is `true`, the declaration is prefixed by
  /// the modifiers and declared type of the variable. Otherwise only the
  /// name and the initializer, if present, are included.
  ///
  /// If [isLate] and [type] are provided, these values are used instead of
  /// the corresponding properties on [node].
  void writeVariableInitialization(
    Variable node, {
    bool includeModifiersAndType = true,
    bool? isLate,
    DartType? type,
    bool includeInitializer = true,
    bool isImplicitlyTyped = false,
  }) {
    if (includeModifiersAndType) {
      if (node.isRequired) {
        _sb.write('required ');
      }
      if (isLate ?? node.isLate) {
        _sb.write('late ');
      }
      if (node.isFinal) {
        _sb.write('final ');
      }
      if (node.isConst) {
        _sb.write('const ');
      }
      if (isImplicitlyTyped) {
        _sb.write('var ');
      } else {
        writeType(type ?? node.type);
        _sb.write(' ');
      }
    }
    _sb.write(getVariableName(node));
    if (includeInitializer && node.initializer != null && !node.isRequired) {
      _sb.write(' = ');
      writeExpression(node.initializer!);
    }
  }

  /// Writes the variable declaration [node] to the printer buffer.
  ///
  /// If [includeModifiersAndType] is `true`, the declaration is prefixed by
  /// the modifiers and declared type of the variable. Otherwise only the
  /// name and the initializer, if present, are included.
  ///
  /// If [isLate] and [type] are provided, these values are used instead of
  /// the corresponding properties on [node].
  void writeExpressionVariable(
    Variable node, {
    bool includeModifiersAndType = true,
    bool? isLate,
    DartType? type,
  }) {
    if (includeModifiersAndType) {
      if (node is FunctionParameter && node.isRequired) {
        _sb.write('required ');
      }
      if (isLate ?? (node is! FunctionParameter && node.isLate)) {
        _sb.write('late ');
      }
      if (node is! FunctionParameter && node.isFinal) {
        _sb.write('final ');
      }
      if (node is! FunctionParameter && node.isConst) {
        _sb.write('const ');
      }
      writeType(type ?? node.type);
      _sb.write(' ');
    }
    _sb.write(getVariableName(node));
  }

  void writeFunctionNode(FunctionNode node, String name) {
    writeType(node.returnType);
    _sb.write(' ');
    _sb.write(name);
    if (node.typeParameters.isNotEmpty) {
      _sb.write('<');
      for (int index = 0; index < node.typeParameters.length; index++) {
        if (index > 0) {
          _sb.write(', ');
        }
        _sb.write(node.typeParameters[index].name);
        _sb.write(' extends ');
        writeType(node.typeParameters[index].bound);
      }
      _sb.write('>');
    }
    _sb.write('(');
    for (int index = 0; index < node.positionalParameters.length; index++) {
      if (index > 0) {
        _sb.write(', ');
      }
      if (index == node.requiredParameterCount) {
        _sb.write('[');
      }
      writeVariableInitialization(node.positionalParameters[index]);
    }
    if (node.requiredParameterCount < node.positionalParameters.length) {
      _sb.write(']');
    }
    if (node.namedParameters.isNotEmpty) {
      if (node.positionalParameters.isNotEmpty) {
        _sb.write(', ');
      }
      _sb.write('{');
      for (int index = 0; index < node.namedParameters.length; index++) {
        if (index > 0) {
          _sb.write(', ');
        }
        writeVariableInitialization(node.namedParameters[index]);
      }
      _sb.write('}');
    }
    _sb.write(')');
    Statement? body = node.body;
    if (body != null) {
      if (body is ReturnStatement) {
        _sb.write(' => ');
        writeExpression(body.expression!);
      } else {
        _sb.write(' ');
        writeStatement(body);
      }
    } else {
      _sb.write(';');
    }
  }

  void writeConstantMapEntry(ConstantMapEntry node) {
    node.toTextInternal(this);
  }

  /// Returns the text written to this printer.
  String getText() => _sb.toString();
}

class MarkingAstPrinter extends AstPrinter {
  Set<TreeNode> markThis;
  new(super.strategy, this.markThis);

  @override
  void writeStatement(Statement node) {
    bool mark = markThis.contains(node);
    if (mark) write("***");
    super.writeStatement(node);
    if (mark) write("***");
  }

  @override
  void writeExpression(Expression node, {int? minimumPrecedence}) {
    bool mark = markThis.contains(node);
    if (mark) write("***");
    super.writeExpression(node, minimumPrecedence: minimumPrecedence);
    if (mark) write("***");
  }
}
