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

import '../../resolution/driver_resolution.dart';

class BaseDependencyTest extends DriverResolutionTest {
//  DependencyTracker tracker;
  String a;
  String b;
  String c;
  Uri aUri;
  Uri bUri;
  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');
//    }

    newFile(path, content: content);
    driver.changeFile(path);

    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('/test/lib/a.dart');
    b = convertPath('/test/lib/b.dart');
    c = convertPath('/test/lib/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 resolvedLibrary = await driver.getResolvedLibrary(libraryPath);
    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,
  });
}
