// 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:analyzer/dart/analysis/results.dart';
import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/src/dart/analysis/dependency/library_builder.dart';
import 'package:analyzer/src/dart/analysis/dependency/node.dart';
import 'package:test/test.dart';

import '../../resolution/context_collection_resolution.dart';

class BaseDependencyTest extends PubPackageResolutionTest {
  late final String a;
  late final String b;
  late final String c;
  late final Uri aUri;
  late final Uri bUri;
  late final Uri cUri;

  bool hasDartCore = false;

  void assertNodes(List<Node> actualNodes, List<ExpectedNode> expectedNodes,
      {Node? expectedEnclosingClass}) {
    expect(actualNodes, hasLength(expectedNodes.length));
    for (var expectedNode in expectedNodes) {
      var topNode = _getNode(
        actualNodes,
        uri: expectedNode.uri,
        name: expectedNode.name,
        kind: expectedNode.kind,
      );
      expect(topNode.enclosingClass, expectedEnclosingClass);

      if (expectedNode.classMembers != null) {
        assertNodes(topNode.classMembers!, expectedNode.classMembers!,
            expectedEnclosingClass: topNode);
      } else {
        expect(topNode.classMembers, isNull);
      }

      if (expectedNode.classTypeParameters != null) {
        assertNodes(
          topNode.classTypeParameters!,
          expectedNode.classTypeParameters!,
          expectedEnclosingClass: topNode,
        );
      } else {
        expect(topNode.classTypeParameters, isNull);
      }
    }
  }

  Future<Library> buildTestLibrary(String path, String content) async {
//    if (!hasDartCore) {
//      hasDartCore = true;
//      await _addLibraryByUri('dart:core');
//      await _addLibraryByUri('dart:async');
//      await _addLibraryByUri('dart:math');
//      await _addLibraryByUri('dart:_internal');
//    }

    newFile2(path, content);

    var analysisDriver = driverFor(path);
    analysisDriver.changeFile(path);
    await analysisDriver.applyPendingFileChanges();

    var units = await _resolveLibrary(path);
    var uri = units.first.declaredElement!.source.uri;

    return buildLibrary(uri, units);

//    tracker.addLibrary(uri, units);
//
//    var library = tracker.libraries[uri];
//    expect(library, isNotNull);
//
//    return library;
  }

  Node getNode(Library library,
      {required String name,
      NodeKind? kind,
      String? memberOf,
      String? typeParameterOf}) {
    var uri = library.uri;
    var nodes = library.declaredNodes;
    if (memberOf != null) {
      var class_ = _getNode(nodes, uri: uri, name: memberOf);
      expect(
        class_.kind,
        anyOf(NodeKind.CLASS, NodeKind.ENUM, NodeKind.MIXIN),
      );
      nodes = class_.classMembers!;
    } else if (typeParameterOf != null) {
      var class_ = _getNode(nodes, uri: uri, name: typeParameterOf);
      expect(class_.kind, anyOf(NodeKind.CLASS, NodeKind.MIXIN));
      nodes = class_.classTypeParameters!;
    }
    return _getNode(nodes, uri: uri, name: name, kind: kind);
  }

  @override
  void setUp() {
    super.setUp();
//    var logger = PerformanceLog(null);
//    tracker = DependencyTracker(logger);
    a = convertPath('$testPackageLibPath/a.dart');
    b = convertPath('$testPackageLibPath/b.dart');
    c = convertPath('$testPackageLibPath/c.dart');
    aUri = Uri.parse('package:test/a.dart');
    bUri = Uri.parse('package:test/b.dart');
    cUri = Uri.parse('package:test/c.dart');
  }

//  Future _addLibraryByUri(String uri) async {
//    var path = driver.sourceFactory.forUri(uri).fullName;
//    var unitResult = await driver.getUnitElement(path);
//
//    var signature = ApiSignature();
//    signature.addString(unitResult.signature);
//    var signatureBytes = signature.toByteList();
//
//    tracker.addLibraryElement(unitResult.element.library, signatureBytes);
//  }

  Node _getNode(List<Node> nodes,
      {required Uri uri, required String name, NodeKind? kind}) {
    var nameObj = LibraryQualifiedName(uri, name);
    for (var node in nodes) {
      if (node.name == nameObj) {
        if (kind != null && node.kind != kind) {
          fail('Expected $kind "$name", found ${node.kind}');
        }
        return node;
      }
    }
    fail('Expected to find $uri::$name in:\n    ${nodes.join('\n    ')}');
  }

  Future<List<CompilationUnit>> _resolveLibrary(String libraryPath) async {
    var session = contextFor(libraryPath).currentSession;
    var resolvedLibrary = await session.getResolvedLibrary(libraryPath);
    resolvedLibrary as ResolvedLibraryResult;
    return resolvedLibrary.units.map((ru) => ru.unit).toList();
  }
}

class ExpectedNode {
  final Uri uri;
  final String name;
  final NodeKind kind;
  final List<ExpectedNode>? classMembers;
  final List<ExpectedNode>? classTypeParameters;

  ExpectedNode(
    this.uri,
    this.name,
    this.kind, {
    this.classMembers,
    this.classTypeParameters,
  });
}
