// 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/dart/element/element.dart';
import 'package:analyzer/src/dart/element/element.dart';
import 'package:test_reflective_loader/test_reflective_loader.dart';

import 'driver_resolution.dart';

main() {
  defineReflectiveSuite(() {
    defineReflectiveTests(OptionalConstDriverResolutionTest);
  });
}

@reflectiveTest
class OptionalConstDriverResolutionTest extends DriverResolutionTest {
  Map<String, LibraryElement> libraries = {};

  LibraryElement get libraryA => libraries['package:test/a.dart'];

  test_instantiateToBounds_notPrefixed_named() async {
    var creation = await _resolveImplicitConst('B.named()');
    assertInstanceCreation(
      creation,
      libraryA.getType('B'),
      'B<num>',
      constructorName: 'named',
      expectedConstructorMember: true,
      expectedSubstitution: {'T': 'num'},
    );
  }

  test_instantiateToBounds_notPrefixed_unnamed() async {
    var creation = await _resolveImplicitConst('B()');
    assertInstanceCreation(
      creation,
      libraryA.getType('B'),
      'B<num>',
      expectedConstructorMember: true,
      expectedSubstitution: {'T': 'num'},
    );
  }

  test_instantiateToBounds_prefixed_named() async {
    var creation = await _resolveImplicitConst('p.B.named()', prefix: 'p');
    assertInstanceCreation(
      creation,
      libraryA.getType('B'),
      'B<num>',
      constructorName: 'named',
      expectedConstructorMember: true,
      expectedSubstitution: {'T': 'num'},
      expectedPrefix: _importOfA()?.prefix,
    );
  }

  test_instantiateToBounds_prefixed_unnamed() async {
    var creation = await _resolveImplicitConst('p.B()', prefix: 'p');
    assertInstanceCreation(
      creation,
      libraryA.getType('B'),
      'B<num>',
      expectedConstructorMember: true,
      expectedSubstitution: {'T': 'num'},
      expectedPrefix: _importOfA()?.prefix,
    );
  }

  test_notPrefixed_named() async {
    var creation = await _resolveImplicitConst('A.named()');
    assertInstanceCreation(
      creation,
      libraryA.getType('A'),
      'A',
      constructorName: 'named',
    );
  }

  test_notPrefixed_unnamed() async {
    var creation = await _resolveImplicitConst('A()');
    assertInstanceCreation(
      creation,
      libraryA.getType('A'),
      'A',
    );
  }

  test_prefixed_named() async {
    var creation = await _resolveImplicitConst('p.A.named()', prefix: 'p');
    // Note, that we don't resynthesize the import prefix.
    assertInstanceCreation(
      creation,
      libraryA.getType('A'),
      'A',
      constructorName: 'named',
      expectedPrefix: _importOfA()?.prefix,
    );
  }

  test_prefixed_unnamed() async {
    var creation = await _resolveImplicitConst('p.A()', prefix: 'p');
    // Note, that we don't resynthesize the import prefix.
    assertInstanceCreation(
      creation,
      libraryA.getType('A'),
      'A',
      expectedPrefix: _importOfA()?.prefix,
    );
  }

  test_prefixed_unnamed_generic() async {
    newFile('/test/lib/a.dart', content: r'''
class C<T> {
  const C();
}
''');
    await assertNoErrorsInCode(r'''
import 'a.dart' as p;

const x = p.C<int>();
''');
    _fillLibraries();

    var element_C = libraryA.getType('C');
    var element_p = findElement.prefix('p');

    var creation = findNode.instanceCreation('p.C<int>()');
    assertType(creation, 'C<int>');

    var constructorName = creation.constructorName;

    var typeName = constructorName.type;
    assertType(typeName, 'C<int>');

    var pC = typeName.name as PrefixedIdentifier;
    assertElement(pC, element_C);
    // TODO(scheglov) enforce
//    assertTypeNull(pC);

    var ref_p = pC.prefix;
    assertElement(ref_p, element_p);
    assertTypeNull(ref_p);

    var ref_C = pC.identifier;
    assertElement(ref_C, element_C);
    assertTypeNull(ref_C);

    assertType(typeName.typeArguments.arguments[0], 'int');
  }

  void _fillLibraries([LibraryElement library]) {
    library ??= result.unit.declaredElement.library;
    var uriStr = library.source.uri.toString();
    if (!libraries.containsKey(uriStr)) {
      libraries[uriStr] = library;
      library.importedLibraries.forEach(_fillLibraries);
    }
  }

  ImportElement _importOfA() {
    var importOfB = findElement.import('package:test/b.dart');
    return importOfB.importedLibrary.imports[0];
  }

  Future<InstanceCreationExpression> _resolveImplicitConst(String expr,
      {String prefix}) async {
    newFile('/test/lib/a.dart', content: '''
class A {
  const A();
  const A.named();
}
class B<T extends num> {
  const B();
  const B.named();
}
''');

    if (prefix != null) {
      newFile('/test/lib/b.dart', content: '''
import 'a.dart' as $prefix;
const a = $expr;
''');
    } else {
      newFile('/test/lib/b.dart', content: '''
import 'a.dart';
const a = $expr;
''');
    }

    await resolveTestCode(r'''
import 'b.dart';
var v = a;
''');
    _fillLibraries();

    PropertyAccessorElement vg = findNode.simple('a;').staticElement;
    var v = vg.variable as ConstVariableElement;

    InstanceCreationExpression creation = v.constantInitializer;
    return creation;
  }
}
