// 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 'package:analysis_server/src/services/correction/dart/abstract_producer.dart';
import 'package:analysis_server/src/services/correction/fix.dart';
import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/dart/ast/token.dart';
import 'package:analyzer/src/dart/ast/extensions.dart';
import 'package:analyzer_plugin/utilities/change_builder/change_builder_core.dart';
import 'package:analyzer_plugin/utilities/fixes/fixes.dart';
import 'package:analyzer_plugin/utilities/range_factory.dart';

class ReplaceWithInterpolation extends CorrectionProducer {
  @override
  FixKind get fixKind => DartFixKind.REPLACE_WITH_INTERPOLATION;

  @override
  Future<void> compute(ChangeBuilder builder) async {
    //
    // Validate the fix.
    //
    BinaryExpression? binary;
    AstNode? candidate = node;
    while (candidate is BinaryExpression && _isStringConcatenation(candidate)) {
      binary = candidate;
      candidate = candidate.parent;
    }
    if (binary == null) {
      return;
    }
    //
    // Extract the information needed to build the edit.
    //
    var components = <AstNode>[];
    var style = _extractComponentsInto(binary, components);
    if (style.isInvalid || style.isUnknown || style.isRaw) {
      return;
    }
    var interpolation = _mergeComponents(style, components);
    //
    // Build the edit.
    //
    final binary_final = binary;
    await builder.addDartFileEdit(file, (builder) {
      builder.addSimpleReplacement(range.node(binary_final), interpolation);
    });
  }

  _StringStyle _extractComponentsInto(
      Expression expression, List<AstNode> components) {
    if (expression is SingleStringLiteral) {
      components.add(expression);
      return _StringStyle(
        multiline: expression.isMultiline,
        raw: expression.isRaw,
        singleQuoted: expression.isSingleQuoted,
      );
    } else if (expression is AdjacentStrings) {
      var style = _StringStyle.unknown;
      for (var string in expression.strings) {
        if (style.isUnknown) {
          style = _extractComponentsInto(string, components);
        } else {
          var currentStyle = _extractComponentsInto(string, components);
          if (style != currentStyle) {
            style = _StringStyle.invalid;
          }
        }
      }
      return style;
    } else if (expression is BinaryExpression &&
        _isStringConcatenation(expression)) {
      var leftStyle =
          _extractComponentsInto(expression.leftOperand, components);
      var rightStyle =
          _extractComponentsInto(expression.rightOperand, components);
      if (leftStyle.isUnknown) {
        return rightStyle;
      } else if (rightStyle.isUnknown) {
        return leftStyle;
      }
      return leftStyle == rightStyle ? leftStyle : _StringStyle.invalid;
    } else if (expression is MethodInvocation) {
      var target = expression.target;
      if (target != null && expression.methodName.name == 'toString') {
        return _extractComponentsInto(target, components);
      }
    } else if (expression is ParenthesizedExpression) {
      return _extractComponentsInto(expression.expression, components);
    }
    components.add(expression);
    return _StringStyle.unknown;
  }

  bool _isStringConcatenation(AstNode node) =>
      node is BinaryExpression &&
      node.operator.type == TokenType.PLUS &&
      node.leftOperand.typeOrThrow.isDartCoreString &&
      node.rightOperand.typeOrThrow.isDartCoreString;

  String _mergeComponents(_StringStyle style, List<AstNode> components) {
    var quotes = style.quotes;
    var buffer = StringBuffer();
    buffer.write(quotes);
    for (var i = 0; i < components.length; i++) {
      var component = components[i];
      if (component is SingleStringLiteral) {
        var contents = utils.getRangeText(range.startOffsetEndOffset(
            component.contentsOffset, component.contentsEnd));
        buffer.write(contents);
      } else if (component is SimpleIdentifier) {
        if (_nextStartsWithIdentifierContinuation(components, i)) {
          buffer.write(r'${');
          buffer.write(component.name);
          buffer.write('}');
        } else {
          buffer.write(r'$');
          buffer.write(component.name);
        }
      } else {
        buffer.write(r'${');
        buffer.write(utils.getNodeText(component));
        buffer.write('}');
      }
    }
    buffer.write(quotes);
    return buffer.toString();
  }

  /// Return `true` if the component after [index] in the list of [components]
  /// is one that would begin with a valid identifier continuation character
  /// when written into the resulting string.
  bool _nextStartsWithIdentifierContinuation(
      List<AstNode> components, int index) {
    bool startsWithIdentifierContinuation(String string) =>
        string.startsWith(RegExp(r'[a-zA-Z0-9_$]'));

    if (index + 1 >= components.length) {
      return false;
    }
    var next = components[index + 1];
    if (next is SimpleStringLiteral) {
      return startsWithIdentifierContinuation(next.value);
    } else if (next is StringInterpolation) {
      return startsWithIdentifierContinuation(
          (next.elements[0] as InterpolationString).value);
    }
    return false;
  }

  /// Return an instance of this class. Used as a tear-off in `FixProcessor`.
  static ReplaceWithInterpolation newInstance() => ReplaceWithInterpolation();
}

class _StringStyle {
  static _StringStyle invalid = _StringStyle._(-2);

  static _StringStyle unknown = _StringStyle._(-1);

  static int multilineBit = 4;
  static int rawBit = 2;
  static int singleQuotedBit = 1;

  final int state;

  factory _StringStyle({
    required bool multiline,
    required bool raw,
    required bool singleQuoted,
  }) {
    return _StringStyle._((multiline ? multilineBit : 0) +
        (raw ? rawBit : 0) +
        (singleQuoted ? singleQuotedBit : 0));
  }

  _StringStyle._(this.state);

  @override
  int get hashCode => state;

  bool get isInvalid => state == -2;

  bool get isRaw => state & rawBit != 0;

  bool get isUnknown => state == -1;

  String get quotes {
    if (state & singleQuotedBit != 0) {
      return (state & multilineBit != 0) ? "'''" : "'";
    }
    return (state & multilineBit != 0) ? '"""' : '"';
  }

  @override
  bool operator ==(Object other) {
    return other is _StringStyle && state == other.state;
  }
}
