// Copyright (c) 2018, 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/protocol_server.dart' hide Element;
import 'package:analysis_server/src/services/correction/status.dart';
import 'package:analysis_server/src/services/correction/util.dart';
import 'package:analysis_server/src/services/refactoring/naming_conventions.dart';
import 'package:analysis_server/src/services/refactoring/refactoring.dart';
import 'package:analysis_server/src/services/refactoring/refactoring_internal.dart';
import 'package:analysis_server/src/services/search/element_visitors.dart';
import 'package:analysis_server/src/services/search/search_engine.dart';
import 'package:analysis_server/src/utilities/flutter.dart';
import 'package:analyzer/dart/analysis/features.dart';
import 'package:analyzer/dart/analysis/results.dart';
import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/dart/ast/visitor.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/dart/element/nullability_suffix.dart';
import 'package:analyzer/dart/element/type.dart';
import 'package:analyzer/src/dart/analysis/session_helper.dart';
import 'package:analyzer/src/dart/ast/extensions.dart';
import 'package:analyzer/src/dart/ast/utilities.dart';
import 'package:analyzer/src/generated/java_core.dart';
import 'package:analyzer/src/generated/source.dart' show SourceRange;
import 'package:analyzer_plugin/utilities/change_builder/change_builder_core.dart';
import 'package:analyzer_plugin/utilities/change_builder/change_builder_dart.dart';
import 'package:analyzer_plugin/utilities/range_factory.dart';

/// [ExtractWidgetRefactoring] implementation.
class ExtractWidgetRefactoringImpl extends RefactoringImpl
    implements ExtractWidgetRefactoring {
  final SearchEngine searchEngine;
  final ResolvedUnitResult resolveResult;
  final AnalysisSessionHelper sessionHelper;
  final int offset;
  final int length;

  late CorrectionUtils utils;

  ClassElement? classBuildContext;
  ClassElement? classKey;
  ClassElement? classStatelessWidget;
  ClassElement? classWidget;
  PropertyAccessorElement? accessorRequired;

  @override
  late String name;

  /// If [offset] is in a class, the node of this class, `null` otherwise.
  ClassDeclaration? _enclosingClassNode;

  /// If [offset] is in a class, the element of this class, `null` otherwise.
  ClassElement? _enclosingClassElement;

  /// The [CompilationUnitMember] that encloses the [offset].
  CompilationUnitMember? _enclosingUnitMember;

  /// The widget creation expression to extract.
  InstanceCreationExpression? _expression;

  /// The statements covered by [offset] and [length] to extract.
  List<Statement>? _statements;

  /// The [SourceRange] that covers [_statements].
  SourceRange? _statementsRange;

  /// The method returning widget to extract.
  MethodDeclaration? _method;

  /// The parameters for the new widget class - referenced fields of the
  /// [_enclosingClassElement], local variables referenced by [_expression],
  /// and [_method] parameters.
  final List<_Parameter> _parameters = [];

  ExtractWidgetRefactoringImpl(
      this.searchEngine, this.resolveResult, this.offset, this.length)
      : sessionHelper = AnalysisSessionHelper(resolveResult.session) {
    utils = CorrectionUtils(resolveResult);
  }

  @override
  String get refactoringName {
    return 'Extract Widget';
  }

  FeatureSet get _featureSet {
    return resolveResult.unit!.featureSet;
  }

  Flutter get _flutter => Flutter.instance;

  bool get _isNonNullable => _featureSet.isEnabled(Feature.non_nullable);

  @override
  Future<RefactoringStatus> checkFinalConditions() async {
    var result = RefactoringStatus();
    result.addStatus(validateClassName(name));
    return result;
  }

  @override
  Future<RefactoringStatus> checkInitialConditions() async {
    var result = RefactoringStatus();

    result.addStatus(_checkSelection());
    if (result.hasFatalError) {
      return result;
    }

    var astNode = _expression ?? _method ?? _statements!.first;
    _enclosingUnitMember = astNode.thisOrAncestorMatching((n) {
      return n is CompilationUnitMember && n.parent is CompilationUnit;
    });

    result.addStatus(await _initializeClasses());
    result.addStatus(await _initializeParameters());

    return result;
  }

  @override
  RefactoringStatus checkName() {
    var result = RefactoringStatus();

    // Validate the name.
    result.addStatus(validateClassName(name));

    // Check for duplicate declarations.
    if (!result.hasFatalError) {
      visitLibraryTopLevelElements(resolveResult.libraryElement, (element) {
        if (hasDisplayName(element, name)) {
          var message = format("Library already declares {0} with name '{1}'.",
              getElementKindName(element), name);
          result.addError(message, newLocation_fromElement(element));
        }
      });
    }

    return result;
  }

  @override
  Future<SourceChange> createChange() async {
    var builder =
        ChangeBuilder(session: sessionHelper.session, eol: utils.endOfLine);
    await builder.addDartFileEdit(resolveResult.path!, (builder) {
      final expression = _expression;
      final statements = _statements;
      if (expression != null) {
        builder.addReplacement(range.node(expression), (builder) {
          _writeWidgetInstantiation(builder);
        });
      } else if (statements != null) {
        builder.addReplacement(_statementsRange!, (builder) {
          builder.write('return ');
          _writeWidgetInstantiation(builder);
          builder.write(';');
        });
      } else {
        _removeMethodDeclaration(builder);
        _replaceInvocationsWithInstantiations(builder);
      }

      _writeWidgetDeclaration(builder);
    });
    return builder.sourceChange;
  }

  @override
  bool isAvailable() {
    return !_checkSelection().hasFatalError;
  }

  /// Checks if [offset] is a widget creation expression that can be extracted.
  RefactoringStatus _checkSelection() {
    var node =
        NodeLocator(offset, offset + length).searchWithin(resolveResult.unit);

    // Treat single ReturnStatement as its expression.
    if (node is ReturnStatement) {
      node = node.expression;
    }

    // Find the enclosing class.
    _enclosingClassNode = node?.thisOrAncestorOfType<ClassDeclaration>();
    _enclosingClassElement = _enclosingClassNode?.declaredElement;

    // new MyWidget(...)
    var newExpression = _flutter.identifyNewExpression(node);
    if (_flutter.isWidgetCreation(newExpression)) {
      _expression = newExpression;
      return RefactoringStatus();
    }

    // Block with selected statements.
    if (node is Block) {
      var selectionRange = SourceRange(offset, length);
      var statements = <Statement>[];
      for (var statement in node.statements) {
        var statementRange = range.node(statement);
        if (statementRange.intersects(selectionRange)) {
          statements.add(statement);
        }
      }
      if (statements.isNotEmpty) {
        var lastStatement = statements.last;
        if (lastStatement is ReturnStatement &&
            _flutter.isWidgetExpression(lastStatement.expression)) {
          _statements = statements;
          _statementsRange = range.startEnd(statements.first, statements.last);
          return RefactoringStatus();
        } else {
          return RefactoringStatus.fatal(
              'The last selected statement must return a widget.');
        }
      }
    }

    // Widget myMethod(...) { ... }
    for (; node != null; node = node.parent) {
      if (node is FunctionBody) {
        break;
      }
      if (node is MethodDeclaration) {
        var returnType = node.returnType?.type;
        if (_flutter.isWidgetType(returnType)) {
          _method = node;
          return RefactoringStatus();
        }
        break;
      }
    }

    // Invalid selection.
    return RefactoringStatus.fatal(
        'Can only extract a widget expression or a method returning widget.');
  }

  Future<RefactoringStatus> _initializeClasses() async {
    var result = RefactoringStatus();

    Future<ClassElement?> getClass(String name) async {
      var element = await sessionHelper.getClass(_flutter.widgetsUri, name);
      if (element == null) {
        result.addFatalError(
          "Unable to find '$name' in ${_flutter.widgetsUri}",
        );
      }
      return element;
    }

    Future<PropertyAccessorElement?> getAccessor(
        String uri, String name) async {
      var element = await sessionHelper.getTopLevelPropertyAccessor(uri, name);
      if (element == null) {
        result.addFatalError("Unable to find 'required' in $uri");
      }
      return element;
    }

    classBuildContext = await getClass('BuildContext');
    classKey = await getClass('Key');
    classStatelessWidget = await getClass('StatelessWidget');
    classWidget = await getClass('Widget');

    accessorRequired = await getAccessor('package:meta/meta.dart', 'required');

    return result;
  }

  /// Prepare referenced local variables and fields, that should be turned
  /// into the widget class fields and constructor parameters.
  Future<RefactoringStatus> _initializeParameters() async {
    _ParametersCollector? collector;

    final expression = _expression;
    if (expression != null) {
      var localRange = range.node(expression);
      collector = _ParametersCollector(_enclosingClassElement, localRange);
      expression.accept(collector);
    }

    final statements = _statements;
    if (statements != null) {
      collector =
          _ParametersCollector(_enclosingClassElement, _statementsRange!);
      for (var statement in statements) {
        statement.accept(collector);
      }
    }

    final method = _method;
    if (method != null) {
      var localRange = range.node(method);
      collector = _ParametersCollector(_enclosingClassElement, localRange);
      method.body.accept(collector);
    }

    _parameters
      ..clear()
      ..addAll(collector!.parameters);

    // We added fields, now add the method parameters.
    if (method != null) {
      var parameterList = method.parameters;
      if (parameterList != null) {
        for (var parameter in parameterList.parameters) {
          if (parameter is DefaultFormalParameter) {
            parameter = parameter.parameter;
          }
          if (parameter is NormalFormalParameter) {
            _parameters.add(_Parameter(
                parameter.identifier!.name, parameter.declaredElement!.type,
                isMethodParameter: true));
          }
        }
      }
    }

    var status = collector.status;

    // If there is an existing parameter "key" warn the user.
    // We could rename it, but that would require renaming references to it.
    // It is probably pretty rare, and the user can always rename before.
    for (var parameter in _parameters) {
      if (parameter.name == 'key') {
        status.addError(
            "The parameter 'key' will conflict with the widget 'key'.");
      }
    }

    // Collect used public names.
    var usedNames = <String>{};
    for (var parameter in _parameters) {
      if (!parameter.name.startsWith('_')) {
        usedNames.add(parameter.name);
      }
    }

    // Give each private parameter a public name for the constructor.
    for (var parameter in _parameters) {
      var name = parameter.name;
      if (name.startsWith('_')) {
        var baseName = name.substring(1);
        for (var i = 1;; i++) {
          name = i == 1 ? baseName : '$baseName$i';
          if (usedNames.add(name)) {
            break;
          }
        }
      }
      parameter.constructorName = name;
    }

    return collector.status;
  }

  /// Remove the [_method] declaration.
  void _removeMethodDeclaration(DartFileEditBuilder builder) {
    var methodRange = range.node(_method!);
    var linesRange =
        utils.getLinesRange(methodRange, skipLeadingEmptyLines: true);
    builder.addDeletion(linesRange);
  }

  String _replaceIndent(String code, String indentOld, String indentNew) {
    var regExp = RegExp('^$indentOld', multiLine: true);
    return code.replaceAll(regExp, indentNew);
  }

  /// Replace invocations of the [_method] with instantiations of the new
  /// widget class.
  void _replaceInvocationsWithInstantiations(DartFileEditBuilder builder) {
    var collector = _MethodInvocationsCollector(_method!.declaredElement!);
    _enclosingClassNode!.accept(collector);
    for (var invocation in collector.invocations) {
      List<Expression> arguments = invocation.argumentList.arguments;
      builder.addReplacement(range.node(invocation), (builder) {
        builder.write('$name(');

        // Insert field references (as named arguments).
        // Ensure that invocation arguments are named.
        var argumentIndex = 0;
        for (var parameter in _parameters) {
          if (parameter != _parameters.first) {
            builder.write(', ');
          }
          builder.write(parameter.name);
          builder.write(': ');
          if (parameter.isMethodParameter) {
            var argument = arguments[argumentIndex++];
            if (argument is NamedExpression) {
              argument = argument.expression;
            }
            builder.write(utils.getNodeText(argument));
          } else {
            builder.write(parameter.name);
          }
        }
        builder.write(')');
      });
    }
  }

  /// Write declaration of the new widget class.
  void _writeWidgetDeclaration(DartFileEditBuilder builder) {
    builder.addInsertion(_enclosingUnitMember!.end, (builder) {
      builder.writeln();
      builder.writeln();
      builder.writeClassDeclaration(
        name,
        superclass: classStatelessWidget!.instantiate(
          typeArguments: const [],
          nullabilitySuffix: NullabilitySuffix.none,
        ),
        membersWriter: () {
          // Add the constructor.
          builder.write('  ');
          builder.writeConstructorDeclaration(
            name,
            isConst: true,
            parameterWriter: () {
              builder.writeln('{');

              // Add the required `key` parameter.
              builder.write('    ');
              builder.writeParameter(
                'key',
                type: classKey!.instantiate(
                  typeArguments: const [],
                  nullabilitySuffix: _isNonNullable
                      ? NullabilitySuffix.question
                      : NullabilitySuffix.star,
                ),
              );
              builder.writeln(',');

              // Add parameters for fields, local, and method parameters.
              for (var parameter in _parameters) {
                builder.write('    ');
                if (_isNonNullable) {
                  builder.write('required');
                } else {
                  builder.write('@');
                  builder.writeReference(accessorRequired!);
                }
                builder.write(' ');
                if (parameter.constructorName != parameter.name) {
                  builder.writeType(parameter.type);
                  builder.write(' ');
                  builder.write(parameter.constructorName);
                } else {
                  builder.write('this.');
                  builder.write(parameter.name);
                }
                builder.writeln(',');
              }

              builder.write('  }');
            },
            initializerWriter: () {
              for (var parameter in _parameters) {
                if (parameter.constructorName != parameter.name) {
                  builder.write(parameter.name);
                  builder.write(' = ');
                  builder.write(parameter.constructorName);
                  builder.write(', ');
                }
              }
              builder.write('super(key: key)');
            },
          );
          builder.writeln();
          builder.writeln();

          // Add the fields for the parameters.
          if (_parameters.isNotEmpty) {
            for (var parameter in _parameters) {
              builder.write('  ');
              builder.writeFieldDeclaration(parameter.name,
                  isFinal: true, type: parameter.type);
              builder.writeln();
            }
            builder.writeln();
          }

          // Widget build(BuildContext context) { ... }
          builder.writeln('  @override');
          builder.write('  ');
          builder.writeFunctionDeclaration(
            'build',
            returnType: classWidget!.instantiate(
              typeArguments: const [],
              nullabilitySuffix: NullabilitySuffix.none,
            ),
            parameterWriter: () {
              builder.writeParameter(
                'context',
                type: classBuildContext!.instantiate(
                  typeArguments: const [],
                  nullabilitySuffix: NullabilitySuffix.none,
                ),
              );
            },
            bodyWriter: () {
              final expression = _expression;
              if (expression != null) {
                var indentOld = utils.getLinePrefix(expression.offset);
                var indentNew = '    ';

                var code = utils.getNodeText(expression);
                code = _replaceIndent(code, indentOld, indentNew);

                builder.writeln('{');

                builder.write('    return ');
                builder.write(code);
                builder.writeln(';');

                builder.writeln('  }');
              } else if (_statements != null) {
                var indentOld = utils.getLinePrefix(_statementsRange!.offset);
                var indentNew = '    ';

                var code = utils.getRangeText(_statementsRange!);
                code = _replaceIndent(code, indentOld, indentNew);

                builder.writeln('{');

                builder.write(indentNew);
                builder.write(code);
                builder.writeln();

                builder.writeln('  }');
              } else {
                var code = utils.getNodeText(_method!.body);
                builder.writeln(code);
              }
            },
          );
        },
      );
    });
  }

  /// Write instantiation of the new widget class.
  void _writeWidgetInstantiation(DartEditBuilder builder) {
    builder.write('$name(');

    for (var parameter in _parameters) {
      if (parameter != _parameters.first) {
        builder.write(', ');
      }
      builder.write(parameter.constructorName);
      builder.write(': ');
      builder.write(parameter.name);
    }

    builder.write(')');
  }
}

class _MethodInvocationsCollector extends RecursiveAstVisitor<void> {
  final ExecutableElement methodElement;
  final List<MethodInvocation> invocations = [];

  _MethodInvocationsCollector(this.methodElement);

  @override
  void visitMethodInvocation(MethodInvocation node) {
    if (node.methodName.staticElement == methodElement) {
      invocations.add(node);
    } else {
      super.visitMethodInvocation(node);
    }
  }
}

class _Parameter {
  /// The name which is used to reference this parameter in the expression
  /// being extracted, and also the name of the field in the new widget.
  final String name;

  final DartType type;

  /// Whether the parameter is a parameter of the method being extracted.
  final bool isMethodParameter;

  /// If the [name] is private, the public name to use in the new widget
  /// constructor. If the [name] is already public, then the [name].
  late String constructorName;

  _Parameter(this.name, this.type, {this.isMethodParameter = false});
}

class _ParametersCollector extends RecursiveAstVisitor<void> {
  final ClassElement? enclosingClass;
  final SourceRange expressionRange;

  final RefactoringStatus status = RefactoringStatus();
  final Set<Element> uniqueElements = <Element>{};
  final List<_Parameter> parameters = [];

  List<ClassElement>? enclosingClasses;

  _ParametersCollector(this.enclosingClass, this.expressionRange);

  @override
  void visitSimpleIdentifier(SimpleIdentifier node) {
    var element = node.writeOrReadElement;
    if (element == null) {
      return;
    }
    var elementName = element.displayName;

    DartType? type;
    if (element is MethodElement) {
      if (_isMemberOfEnclosingClass(element)) {
        status.addError(
            'Reference to an enclosing class method cannot be extracted.');
      }
    } else if (element is LocalVariableElement) {
      if (!expressionRange.contains(element.nameOffset)) {
        if (node.inSetterContext()) {
          status.addError("Write to '$elementName' cannot be extracted.");
        } else {
          type = element.type;
        }
      }
    } else if (element is PropertyAccessorElement) {
      var field = element.variable;
      if (_isMemberOfEnclosingClass(field)) {
        if (node.inSetterContext()) {
          status.addError("Write to '$elementName' cannot be extracted.");
        } else {
          type = field.type;
        }
      }
    }
    // TODO(scheglov) support for ParameterElement

    if (type != null && uniqueElements.add(element)) {
      parameters.add(_Parameter(elementName, type));
    }
  }

  /// Return `true` if the given [element] is a member of the [enclosingClass]
  /// or one of its supertypes, interfaces, or mixins.
  bool _isMemberOfEnclosingClass(Element element) {
    final enclosingClass = this.enclosingClass;
    if (enclosingClass != null) {
      final enclosingClasses = this.enclosingClasses ??= <ClassElement>[]
        ..add(enclosingClass)
        ..addAll(enclosingClass.allSupertypes.map((t) => t.element));
      return enclosingClasses.contains(element.enclosingElement);
    }
    return false;
  }
}
