// 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_plugin/utilities/change_builder/change_builder_dart.dart';
import 'package:analyzer_plugin/utilities/fixes/fixes.dart';
import 'package:analyzer_plugin/utilities/range_factory.dart';
import 'package:meta/meta.dart';

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

  @override
  Future<void> compute(DartChangeBuilder builder) async {
    //
    // Validate the fix.
    //
    BinaryExpression binary;
    var parent = node.parent;
    while (_isStringConcatenation(parent)) {
      binary = parent;
      parent = parent.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.
    //
    await builder.addFileEdit(file, (DartFileEditBuilder builder) {
      builder.addSimpleReplacement(range.node(binary), 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 &&
        expression.methodName.name == 'toString') {
      return _extractComponentsInto(expression.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.staticType.isDartCoreString &&
      node.rightOperand.staticType.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 SimpleStringLiteral) {
        var contents = utils.getRangeText(range.startOffsetEndOffset(
            component.contentsOffset, component.contentsEnd));
        buffer.write(contents);
      } else if (component is SimpleIdentifier) {
        if (_nextStartsWithLetter(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 letter when written into the resulting
  /// string.
  bool _nextStartsWithLetter(List<AstNode> components, int index) {
    bool startsWithLetter(String string) =>
        string.startsWith(RegExp('[a-zA-Z]'));

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

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;
  }
}
