// Copyright (c) 2022, 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/util.dart';
import 'package:analysis_server/src/services/linter/lint_names.dart';
import 'package:analysis_server/src/services/snippets/dart/snippet_manager.dart';
import 'package:analyzer/dart/analysis/features.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/dart/element/nullability_suffix.dart';
import 'package:analyzer/src/dart/analysis/session_helper.dart';
import 'package:analyzer/src/dart/element/type.dart';
import 'package:analyzer/src/lint/linter.dart' show LinterContextImpl;
import 'package:analyzer_plugin/utilities/change_builder/change_builder_core.dart';

/// Produces a [Snippet] that creates a Class definition.
class DartClassSnippetProducer extends DartSnippetProducer {
  static const prefix = 'class';
  static const label = 'class';

  DartClassSnippetProducer._(super.request);

  @override
  Future<Snippet> compute() async {
    final builder = ChangeBuilder(session: request.analysisSession);
    final indent = utils.getLinePrefix(request.offset);

    await builder.addDartFileEdit(request.filePath, (builder) {
      builder.addReplacement(request.replacementRange, (builder) {
        void writeIndented(String string) => builder.write('$indent$string');
        builder.write('class ');
        builder.addSimpleLinkedEdit('className', 'ClassName');
        builder.writeln(' {');
        writeIndented('  ');
        builder.selectHere();
        builder.writeln();
        writeIndented('}');
      });
    });

    return Snippet(
      prefix,
      label,
      'Insert a class definition.',
      builder.sourceChange,
    );
  }

  static DartClassSnippetProducer newInstance(DartSnippetRequest request) =>
      DartClassSnippetProducer._(request);
}

/// Produces a [Snippet] that creates a `do while` loop.
class DartDoWhileLoopSnippetProducer extends DartSnippetProducer {
  static const prefix = 'do';
  static const label = 'do while';

  DartDoWhileLoopSnippetProducer._(super.request);

  @override
  Future<Snippet> compute() async {
    final builder = ChangeBuilder(session: request.analysisSession);
    final indent = utils.getLinePrefix(request.offset);

    await builder.addDartFileEdit(request.filePath, (builder) {
      builder.addReplacement(request.replacementRange, (builder) {
        void writeIndented(String string) => builder.write('$indent$string');
        builder.writeln('do {');
        writeIndented('  ');
        builder.selectHere();
        builder.writeln();
        writeIndented('} while (');
        builder.addSimpleLinkedEdit('condition', 'condition');
        builder.write(');');
      });
    });

    return Snippet(
      prefix,
      label,
      'Insert a do-while loop.',
      builder.sourceChange,
    );
  }

  static DartDoWhileLoopSnippetProducer newInstance(
          DartSnippetRequest request) =>
      DartDoWhileLoopSnippetProducer._(request);
}

/// Produces a [Snippet] that creates a `for in` loop.
class DartForInLoopSnippetProducer extends DartSnippetProducer {
  static const prefix = 'forin';
  static const label = 'for in';

  DartForInLoopSnippetProducer._(super.request);

  @override
  Future<Snippet> compute() async {
    final builder = ChangeBuilder(session: request.analysisSession);
    final indent = utils.getLinePrefix(request.offset);
    final varOrFinal =
        isLintEnabled(LintNames.prefer_final_locals) ? 'final' : 'var';

    await builder.addDartFileEdit(request.filePath, (builder) {
      builder.addReplacement(request.replacementRange, (builder) {
        void writeIndented(String string) => builder.write('$indent$string');
        builder.write('for ($varOrFinal ');
        builder.addSimpleLinkedEdit('elementName', 'element');
        builder.write(' in ');
        builder.addSimpleLinkedEdit('collectionName', 'collection');
        builder.writeln(') {');
        writeIndented('  ');
        builder.selectHere();
        builder.writeln();
        writeIndented('}');
      });
    });

    return Snippet(
      prefix,
      label,
      'Insert a for-in loop.',
      builder.sourceChange,
    );
  }

  static DartForInLoopSnippetProducer newInstance(DartSnippetRequest request) =>
      DartForInLoopSnippetProducer._(request);
}

/// Produces a [Snippet] that creates a `for` loop.
class DartForLoopSnippetProducer extends DartSnippetProducer {
  static const prefix = 'for';
  static const label = 'for';

  DartForLoopSnippetProducer._(super.request);

  @override
  Future<Snippet> compute() async {
    final builder = ChangeBuilder(session: request.analysisSession);
    final indent = utils.getLinePrefix(request.offset);

    await builder.addDartFileEdit(request.filePath, (builder) {
      builder.addReplacement(request.replacementRange, (builder) {
        void writeIndented(String string) => builder.write('$indent$string');
        builder.write('for (var i = 0; i < ');
        builder.addSimpleLinkedEdit('count', 'count');
        builder.writeln('; i++) {');
        writeIndented('  ');
        builder.selectHere();
        builder.writeln();
        writeIndented('}');
      });
    });

    return Snippet(
      prefix,
      label,
      'Insert a for loop.',
      builder.sourceChange,
    );
  }

  static DartForLoopSnippetProducer newInstance(DartSnippetRequest request) =>
      DartForLoopSnippetProducer._(request);
}

/// Produces a [Snippet] that creates a function definition.
class DartFunctionSnippetProducer extends DartSnippetProducer {
  static const prefix = 'fun';
  static const label = 'fun';

  DartFunctionSnippetProducer._(super.request);

  @override
  Future<Snippet> compute() async {
    final builder = ChangeBuilder(session: request.analysisSession);
    final indent = utils.getLinePrefix(request.offset);

    await builder.addDartFileEdit(request.filePath, (builder) {
      builder.addReplacement(request.replacementRange, (builder) {
        void writeIndented(String string) => builder.write('$indent$string');

        builder.addSimpleLinkedEdit('returnType', 'void');
        builder.write(' ');
        builder.addSimpleLinkedEdit('name', 'name');
        builder.write('(');
        builder.addSimpleLinkedEdit('params', 'params');
        builder.writeln(') {');
        writeIndented('  ');
        builder.selectHere();
        builder.writeln();
        writeIndented('}');
      });
    });

    return Snippet(
      prefix,
      label,
      'Insert a function definition.',
      builder.sourceChange,
    );
  }

  static DartFunctionSnippetProducer newInstance(DartSnippetRequest request) =>
      DartFunctionSnippetProducer._(request);
}

/// Produces a [Snippet] that creates an if/else statement.
class DartIfElseSnippetProducer extends DartSnippetProducer {
  static const prefix = 'ife';
  static const label = 'ife';

  DartIfElseSnippetProducer._(super.request);

  @override
  Future<Snippet> compute() async {
    final builder = ChangeBuilder(session: request.analysisSession);
    final indent = utils.getLinePrefix(request.offset);

    await builder.addDartFileEdit(request.filePath, (builder) {
      builder.addReplacement(request.replacementRange, (builder) {
        void writeIndented(String string) => builder.write('$indent$string');
        void writeIndentedln(String string) =>
            builder.writeln('$indent$string');
        builder.write('if (');
        builder.addSimpleLinkedEdit('condition', 'condition');
        builder.writeln(') {');
        writeIndented('  ');
        builder.selectHere();
        builder.writeln();
        writeIndentedln('} else {');
        writeIndentedln('  ');
        writeIndented('}');
      });
    });

    return Snippet(
      prefix,
      label,
      'Insert an if/else statement.',
      builder.sourceChange,
    );
  }

  static DartIfElseSnippetProducer newInstance(DartSnippetRequest request) =>
      DartIfElseSnippetProducer._(request);
}

/// Produces a [Snippet] that creates an if statement.
class DartIfSnippetProducer extends DartSnippetProducer {
  static const prefix = 'if';
  static const label = 'if';

  DartIfSnippetProducer._(super.request);

  @override
  Future<Snippet> compute() async {
    final builder = ChangeBuilder(session: request.analysisSession);
    final indent = utils.getLinePrefix(request.offset);

    await builder.addDartFileEdit(request.filePath, (builder) {
      builder.addReplacement(request.replacementRange, (builder) {
        void writeIndented(String string) => builder.write('$indent$string');
        builder.write('if (');
        builder.addSimpleLinkedEdit('condition', 'condition');
        builder.writeln(') {');
        writeIndented('  ');
        builder.selectHere();
        builder.writeln();
        writeIndented('}');
      });
    });

    return Snippet(
      prefix,
      label,
      'Insert an if statement.',
      builder.sourceChange,
    );
  }

  static DartIfSnippetProducer newInstance(DartSnippetRequest request) =>
      DartIfSnippetProducer._(request);
}

/// Produces a [Snippet] that creates a top-level `main` function.
///
/// A `List<String> args` parameter will be included when generating inside a
/// file in `bin` or `tool` folders.
class DartMainFunctionSnippetProducer extends DartSnippetProducer {
  static const prefix = 'main';
  static const label = 'main()';

  DartMainFunctionSnippetProducer._(super.request);

  /// Whether to insert a `List<String> args` parameter in the generated
  /// function.
  ///
  /// The parameter is suppressed for any known test directories.
  bool get _insertArgsParameter => !isInTestDirectory;

  @override
  Future<Snippet> compute() async {
    final builder = ChangeBuilder(session: request.analysisSession);

    final typeProvider = request.unit.typeProvider;
    final listString = typeProvider.listType(typeProvider.stringType);

    await builder.addDartFileEdit(request.filePath, (builder) {
      builder.addReplacement(request.replacementRange, (builder) {
        builder.writeFunctionDeclaration(
          'main',
          returnType: VoidTypeImpl.instance,
          parameterWriter: _insertArgsParameter
              ? () => builder.writeParameter('args', type: listString)
              : null,
          bodyWriter: () {
            builder.writeln('{');
            builder.write('  ');
            builder.selectHere();
            builder.writeln();
            builder.write('}');
          },
        );
      });
    });

    return Snippet(
      prefix,
      label,
      'Insert a main function, used as an entry point.',
      builder.sourceChange,
    );
  }

  static DartMainFunctionSnippetProducer newInstance(
          DartSnippetRequest request) =>
      DartMainFunctionSnippetProducer._(request);
}

abstract class DartSnippetProducer extends SnippetProducer {
  final AnalysisSessionHelper sessionHelper;
  final CorrectionUtils utils;
  final LibraryElement libraryElement;
  final bool useSuperParams;

  DartSnippetProducer(super.request)
      : sessionHelper = AnalysisSessionHelper(request.analysisSession),
        utils = CorrectionUtils(request.unit),
        libraryElement = request.unit.libraryElement,
        useSuperParams = request.unit.libraryElement.featureSet
            .isEnabled(Feature.super_parameters);

  bool get isInTestDirectory {
    final path = request.unit.path;
    return LinterContextImpl.testDirectories
        .any((testDir) => path.contains(testDir));
  }

  /// The nullable suffix to use in this library.
  NullabilitySuffix get nullableSuffix => libraryElement.isNonNullableByDefault
      ? NullabilitySuffix.question
      : NullabilitySuffix.none;

  bool isLintEnabled(String name) {
    var analysisOptions = sessionHelper.session.analysisContext.analysisOptions;
    return analysisOptions.isLintEnabled(name);
  }
}

/// Produces a [Snippet] that creates an if statement.
class DartSwitchSnippetProducer extends DartSnippetProducer {
  static const prefix = 'switch';
  static const label = 'switch case';

  DartSwitchSnippetProducer._(super.request);

  @override
  Future<Snippet> compute() async {
    final builder = ChangeBuilder(session: request.analysisSession);
    final indent = utils.getLinePrefix(request.offset);

    await builder.addDartFileEdit(request.filePath, (builder) {
      builder.addReplacement(request.replacementRange, (builder) {
        void writeIndented(String string) => builder.write('$indent$string');
        void writeIndentedln(String string) =>
            builder.writeln('$indent$string');
        builder.write('switch (');
        builder.addSimpleLinkedEdit('expression', 'expression');
        builder.writeln(') {');
        writeIndented('  case ');
        builder.addSimpleLinkedEdit('value', 'value');
        builder.writeln(':');
        writeIndented('    ');
        builder.selectHere();
        builder.writeln();
        writeIndentedln('    break;');
        writeIndentedln('  default:');
        writeIndented('}');
      });
    });

    return Snippet(
      prefix,
      label,
      'Insert a switch statement.',
      builder.sourceChange,
    );
  }

  static DartSwitchSnippetProducer newInstance(DartSnippetRequest request) =>
      DartSwitchSnippetProducer._(request);
}

/// Produces a [Snippet] that creates a `test()` block.
class DartTestBlockSnippetProducer extends DartSnippetProducer {
  static const prefix = 'test';
  static const label = 'test';

  DartTestBlockSnippetProducer._(super.request);

  @override
  Future<Snippet> compute() async {
    final builder = ChangeBuilder(session: request.analysisSession);
    final indent = utils.getLinePrefix(request.offset);

    await builder.addDartFileEdit(request.filePath, (builder) {
      builder.addReplacement(request.replacementRange, (builder) {
        void writeIndented(String string) => builder.write('$indent$string');
        builder.write("test('");
        builder.addSimpleLinkedEdit('testName', 'test name');
        builder.writeln("', () {");
        writeIndented('  ');
        builder.selectHere();
        builder.writeln();
        writeIndented('});');
      });
    });

    return Snippet(
      prefix,
      label,
      'Insert a test block.',
      builder.sourceChange,
    );
  }

  @override
  Future<bool> isValid() async {
    if (!await super.isValid()) {
      return false;
    }

    return isInTestDirectory;
  }

  static DartTestBlockSnippetProducer newInstance(DartSnippetRequest request) =>
      DartTestBlockSnippetProducer._(request);
}

/// Produces a [Snippet] that creates a `test()` block.
class DartTestGroupBlockSnippetProducer extends DartSnippetProducer {
  static const prefix = 'group';
  static const label = 'group';

  DartTestGroupBlockSnippetProducer._(super.request);

  @override
  Future<Snippet> compute() async {
    final builder = ChangeBuilder(session: request.analysisSession);
    final indent = utils.getLinePrefix(request.offset);

    await builder.addDartFileEdit(request.filePath, (builder) {
      builder.addReplacement(request.replacementRange, (builder) {
        void writeIndented(String string) => builder.write('$indent$string');
        builder.write("group('");
        builder.addSimpleLinkedEdit('groupName', 'group name');
        builder.writeln("', () {");
        writeIndented('  ');
        builder.selectHere();
        builder.writeln();
        writeIndented('});');
      });
    });

    return Snippet(
      prefix,
      label,
      'Insert a test group block.',
      builder.sourceChange,
    );
  }

  @override
  Future<bool> isValid() async {
    if (!await super.isValid()) {
      return false;
    }

    return isInTestDirectory;
  }

  static DartTestGroupBlockSnippetProducer newInstance(
          DartSnippetRequest request) =>
      DartTestGroupBlockSnippetProducer._(request);
}

/// Produces a [Snippet] that creates a try/catch statement.
class DartTryCatchSnippetProducer extends DartSnippetProducer {
  static const prefix = 'try';
  static const label = 'try';

  DartTryCatchSnippetProducer._(super.request);

  @override
  Future<Snippet> compute() async {
    final builder = ChangeBuilder(session: request.analysisSession);
    final indent = utils.getLinePrefix(request.offset);

    await builder.addDartFileEdit(request.filePath, (builder) {
      builder.addReplacement(request.replacementRange, (builder) {
        void writeIndented(String string) => builder.write('$indent$string');
        void writeIndentedln(String string) =>
            builder.writeln('$indent$string');
        builder.writeln('try {');
        writeIndented('  ');
        builder.selectHere();
        builder.writeln();
        writeIndented('} catch (');
        builder.addLinkedEdit('exceptionName', (builder) {
          builder.write('e');
        });
        builder.writeln(') {');
        writeIndentedln('  ');
        writeIndented('}');
      });
    });

    return Snippet(
      prefix,
      label,
      'Insert a try/catch statement.',
      builder.sourceChange,
    );
  }

  static DartTryCatchSnippetProducer newInstance(DartSnippetRequest request) =>
      DartTryCatchSnippetProducer._(request);
}

/// Produces a [Snippet] that creates a `while` loop.
class DartWhileLoopSnippetProducer extends DartSnippetProducer {
  static const prefix = 'while';
  static const label = 'while';

  DartWhileLoopSnippetProducer._(super.request);

  @override
  Future<Snippet> compute() async {
    final builder = ChangeBuilder(session: request.analysisSession);
    final indent = utils.getLinePrefix(request.offset);

    await builder.addDartFileEdit(request.filePath, (builder) {
      builder.addReplacement(request.replacementRange, (builder) {
        void writeIndented(String string) => builder.write('$indent$string');
        builder.write('while (');
        builder.addSimpleLinkedEdit('condition', 'condition');
        builder.writeln(') {');
        writeIndented('  ');
        builder.selectHere();
        builder.writeln();
        writeIndented('}');
      });
    });

    return Snippet(
      prefix,
      label,
      'Insert a while loop.',
      builder.sourceChange,
    );
  }

  static DartWhileLoopSnippetProducer newInstance(DartSnippetRequest request) =>
      DartWhileLoopSnippetProducer._(request);
}
