// 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:analysis_server/src/services/linter/lint_names.dart';
import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/dart/ast/token.dart';
import 'package:analyzer/error/error.dart';
import 'package:analyzer/source/source_range.dart';
import 'package:analyzer/src/dart/error/hint_codes.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 RemoveComparison extends CorrectionProducer {
  @override
  bool get canBeAppliedInBulk => true;

  @override
  bool get canBeAppliedToFile => true;

  @override
  FixKind get fixKind => DartFixKind.REMOVE_COMPARISON;

  @override
  FixKind get multiFixKind => DartFixKind.REMOVE_COMPARISON_MULTI;

  /// Return `true` if the null comparison will always return `false`.
  bool get _conditionIsFalse =>
      (diagnostic as AnalysisError).errorCode ==
      HintCode.UNNECESSARY_NULL_COMPARISON_FALSE;

  /// Return `true` if the null comparison will always return `true`.
  bool get _conditionIsTrue {
    var errorCode = (diagnostic as AnalysisError).errorCode;
    return errorCode == HintCode.UNNECESSARY_NULL_COMPARISON_TRUE ||
        errorCode.name == LintNames.avoid_null_checks_in_equality_operators;
  }

  @override
  Future<void> compute(ChangeBuilder builder) async {
    var binaryExpression = node;
    if (binaryExpression is! BinaryExpression) {
      return;
    }
    var parent = binaryExpression.parent;
    if (parent is AssertInitializer && _conditionIsTrue) {
      var constructor = parent.parent as ConstructorDeclaration;
      var list = constructor.initializers;
      if (list.length == 1) {
        await builder.addDartFileEdit(file, (builder) {
          builder.addDeletion(range.endEnd(constructor.parameters, parent));
        });
      } else {
        await builder.addDartFileEdit(file, (builder) {
          builder.addDeletion(range.nodeInList(list, parent));
        });
      }
    } else if (parent is AssertStatement && _conditionIsTrue) {
      await builder.addDartFileEdit(file, (builder) {
        builder.addDeletion(utils.getLinesRange(range.node(parent)));
      });
    } else if (parent is BinaryExpression) {
      if (parent.operator.type == TokenType.AMPERSAND_AMPERSAND &&
          _conditionIsTrue) {
        await _removeOperatorAndOperand(builder, parent, binaryExpression);
      } else if (parent.operator.type == TokenType.BAR_BAR &&
          _conditionIsFalse) {
        await _removeOperatorAndOperand(builder, parent, binaryExpression);
      }
    } else if (parent is IfStatement) {
      if (parent.elseStatement == null && _conditionIsTrue) {
        await _ifStatement(parent, builder);
      }
    }
  }

  Future<void> _ifStatement(IfStatement node, ChangeBuilder builder) async {
    await builder.addDartFileEdit(file, (builder) {
      var nodeRange = utils.getLinesRangeStatements([node]);

      String bodyCode;
      var body = node.thenStatement;
      if (body is Block) {
        var statements = body.statements;
        if (statements.isEmpty) {
          builder.addDeletion(nodeRange);
          return;
        } else {
          bodyCode = utils.getRangeText(
            utils.getLinesRangeStatements(statements),
          );
        }
      } else {
        bodyCode = utils.getRangeText(
          utils.getLinesRangeStatements([body]),
        );
      }

      bodyCode = utils.indentSourceLeftRight(bodyCode);
      builder.addSimpleReplacement(nodeRange, bodyCode);
    });
  }

  /// Use the [builder] to add an edit to delete the operator and given
  /// [operand] from the [binary] expression.
  Future<void> _removeOperatorAndOperand(ChangeBuilder builder,
      BinaryExpression binary, Expression operand) async {
    SourceRange operatorAndOperand;
    if (binary.leftOperand == node) {
      operatorAndOperand = range.startStart(node, binary.rightOperand);
    } else {
      operatorAndOperand = range.endEnd(binary.leftOperand, node);
    }
    await builder.addDartFileEdit(file, (builder) {
      builder.addDeletion(operatorAndOperand);
    });
  }

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