// Copyright (c) 2014, 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:analyzer/dart/analysis/results.dart';
import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/dart/element/element2.dart';
import 'package:analyzer/error/error.dart';
import 'package:analyzer/file_system/file_system.dart';
import 'package:analyzer/src/error/codes.g.dart';
import 'package:analyzer/src/test_utilities/find_element.dart';
import 'package:analyzer/src/test_utilities/find_element2.dart';
import 'package:analyzer/src/test_utilities/find_node.dart';
import 'package:analyzer/src/utilities/extensions/analysis_session.dart';
import 'package:analyzer/src/utilities/extensions/element.dart';
import 'package:test/test.dart';

import 'abstract_context.dart';

class AbstractSingleUnitTest extends AbstractContextTest {
  bool verifyNoTestUnitErrors = true;

  late String testCode;
  late ParsedUnitResult testParsedResult;
  late ResolvedLibraryResult? testLibraryResult;
  late ResolvedUnitResult testAnalysisResult;
  late CompilationUnit testUnit;
  late CompilationUnitElement testUnitElement;
  late LibraryElement testLibraryElement;
  late FindNode findNode;
  late FindElement findElement;
  late FindElement2 findElement2;

  LibraryElement2 get testLibraryElement2 => testLibraryElement.asElement2;

  void addTestSource(String code) {
    testCode = code;
    newFile(testFile.path, code);
  }

  int findEnd(String search) {
    return findOffset(search) + search.length;
  }

  int findOffset(String search) {
    var offset = testCode.indexOf(search);
    expect(offset, isNonNegative, reason: "Not found '$search' in\n$testCode");
    return offset;
  }

  @override
  Future<ParsedUnitResult> getParsedUnit(File file) async {
    var unitResult = await super.getParsedUnit(file);
    testParsedResult = unitResult;
    testCode = unitResult.content;
    testUnit = unitResult.unit;
    findNode = FindNode(testCode, testUnit);
    findElement = FindElement(testUnit);
    findElement2 = FindElement2(testUnit);
    return unitResult;
  }

  @override
  Future<ResolvedUnitResult> getResolvedUnit(File file) async {
    var session = await this.session;
    testLibraryResult = await session.getResolvedContainingLibrary(file.path);
    var unitResult = testLibraryResult?.unitWithPath(file.path);
    unitResult ??= await super.getResolvedUnit(file);
    testAnalysisResult = unitResult;
    testCode = testAnalysisResult.content;
    testUnit = testAnalysisResult.unit;
    if (verifyNoTestUnitErrors) {
      expect(
        testAnalysisResult.errors.where((AnalysisError error) {
          return error.errorCode != WarningCode.DEAD_CODE &&
              error.errorCode != WarningCode.UNUSED_CATCH_CLAUSE &&
              error.errorCode != WarningCode.UNUSED_CATCH_STACK &&
              error.errorCode != WarningCode.UNUSED_ELEMENT &&
              error.errorCode != WarningCode.UNUSED_FIELD &&
              error.errorCode != WarningCode.UNUSED_IMPORT &&
              error.errorCode != WarningCode.UNUSED_LOCAL_VARIABLE;
        }),
        isEmpty,
      );
    }
    testUnitElement = testUnit.declaredElement!;
    testLibraryElement = testUnitElement.library;
    findNode = FindNode(testCode, testUnit);
    findElement = FindElement(testUnit);
    findElement2 = FindElement2(testUnit);
    return testAnalysisResult;
  }

  Future<void> parseTestCode(String code) async {
    addTestSource(code);
    await getParsedUnit(testFile);
  }

  Future<void> resolveTestCode(String code) async {
    addTestSource(code);
    await resolveTestFile();
  }

  Future<void> resolveTestFile() async {
    await getResolvedUnit(testFile);
  }
}
