// 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.

library test.services.refactoring.move_files;

import 'dart:async';

import 'package:analysis_server/src/services/refactoring/refactoring.dart';
import 'package:analyzer/file_system/file_system.dart';
import 'package:analyzer/source/package_map_resolver.dart';
import 'package:analyzer/src/generated/engine.dart';
import 'package:analyzer/src/generated/source.dart';
import 'package:test_reflective_loader/test_reflective_loader.dart';

import '../../abstract_context.dart';
import '../../utils.dart';
import 'abstract_refactoring.dart';

main() {
  initializeTestEnvironment();
  defineReflectiveTests(MoveFileTest);
}

@reflectiveTest
class MoveFileTest extends RefactoringTest {
  MoveFileRefactoring refactoring;

  test_file_definingUnit() async {
    String pathA = '/project/000/1111/a.dart';
    String pathB = '/project/000/1111/b.dart';
    String pathC = '/project/000/1111/22/c.dart';
    String pathD = '/project/000/1111/333/d.dart';
    testFile = '/project/000/1111/test.dart';
    addSource('/absolute/uri.dart', '');
    addSource(pathA, 'part of lib;');
    addSource(pathB, "import 'test.dart';");
    addSource(pathC, '');
    addSource(pathD, '');
    addTestSource('''
library lib;
import 'dart:math';
import '22/c.dart';
export '333/d.dart';
part 'a.dart';
part '/absolute/uri.dart';
''');
    _performAnalysis();
    // perform refactoring
    _createRefactoring('/project/000/1111/22/new_name.dart');
    await _assertSuccessfulRefactoring();
    assertNoFileChange(pathA);
    assertFileChangeResult(pathB, "import '22/new_name.dart';");
    assertNoFileChange(pathC);
    assertFileChangeResult(
        testFile,
        '''
library lib;
import 'dart:math';
import 'c.dart';
export '../333/d.dart';
part '../a.dart';
part '/absolute/uri.dart';
''');
  }

  test_file_importedLibrary() async {
    String pathA = '/project/000/1111/a.dart';
    testFile = '/project/000/1111/sub/folder/test.dart';
    addSource(
        pathA,
        '''
import 'sub/folder/test.dart';
''');
    addTestSource('');
    _performAnalysis();
    // perform refactoring
    _createRefactoring('/project/000/new/folder/name/new_name.dart');
    await _assertSuccessfulRefactoring();
    assertFileChangeResult(
        pathA,
        '''
import '../new/folder/name/new_name.dart';
''');
    assertNoFileChange(testFile);
  }

  test_file_importedLibrary_down() async {
    String pathA = '/project/000/1111/a.dart';
    testFile = '/project/000/1111/test.dart';
    addSource(
        pathA,
        '''
import 'test.dart';
''');
    addTestSource('');
    _performAnalysis();
    // perform refactoring
    _createRefactoring('/project/000/1111/22/new_name.dart');
    await _assertSuccessfulRefactoring();
    assertFileChangeResult(
        pathA,
        '''
import '22/new_name.dart';
''');
    assertNoFileChange(testFile);
  }

  test_file_importedLibrary_package() async {
    // configure packages
    testFile = '/packages/my_pkg/aaa/test.dart';
    provider.newFile(testFile, '');
    Map<String, List<Folder>> packageMap = {
      'my_pkg': [provider.getResource('/packages/my_pkg')]
    };
    context.sourceFactory = new SourceFactory([
      AbstractContextTest.SDK_RESOLVER,
      new PackageMapUriResolver(provider, packageMap),
      resourceResolver
    ]);
    // do testing
    String pathA = '/project/bin/a.dart';
    addSource(
        pathA,
        '''
import 'package:my_pkg/aaa/test.dart';
''');
    addTestSource('');
    _performAnalysis();
    // perform refactoring
    _createRefactoring('/packages/my_pkg/bbb/ccc/new_name.dart');
    await _assertSuccessfulRefactoring();
    assertFileChangeResult(
        pathA,
        '''
import 'package:my_pkg/bbb/ccc/new_name.dart';
''');
    assertNoFileChange(testFile);
  }

  test_file_importedLibrary_up() async {
    String pathA = '/project/000/1111/a.dart';
    testFile = '/project/000/1111/22/test.dart';
    addSource(
        pathA,
        '''
import '22/test.dart';
''');
    addTestSource('');
    _performAnalysis();
    // perform refactoring
    _createRefactoring('/project/000/1111/new_name.dart');
    await _assertSuccessfulRefactoring();
    assertFileChangeResult(
        pathA,
        '''
import 'new_name.dart';
''');
    assertNoFileChange(testFile);
  }

  test_file_sourcedUnit() async {
    String pathA = '/project/000/1111/a.dart';
    testFile = '/project/000/1111/22/test.dart';
    addSource(
        pathA,
        '''
library lib;
part '22/test.dart';
''');
    addTestSource('''
part of lib;
''');
    _performAnalysis();
    // perform refactoring
    _createRefactoring('/project/000/1111/22/new_name.dart');
    await _assertSuccessfulRefactoring();
    assertFileChangeResult(
        pathA,
        '''
library lib;
part '22/new_name.dart';
''');
    assertNoFileChange(testFile);
  }

  test_file_sourcedUnit_multipleLibraries() async {
    String pathA = '/project/000/1111/a.dart';
    String pathB = '/project/000/b.dart';
    testFile = '/project/000/1111/22/test.dart';
    addSource(
        pathA,
        '''
library lib;
part '22/test.dart';
''');
    addSource(
        pathB,
        '''
library lib;
part '1111/22/test.dart';
''');
    addTestSource('''
part of lib;
''');
    _performAnalysis();
    // perform refactoring
    _createRefactoring('/project/000/1111/22/new_name.dart');
    await _assertSuccessfulRefactoring();
    assertFileChangeResult(
        pathA,
        '''
library lib;
part '22/new_name.dart';
''');
    assertFileChangeResult(
        pathB,
        '''
library lib;
part '1111/22/new_name.dart';
''');
    assertNoFileChange(testFile);
  }

  test_project() async {
    String pubspecPath = '/testName/pubspec.yaml';
    String appPath = '/testName/bin/myApp.dart';
    provider.newFile(
        pubspecPath,
        '''
name: testName
version: 0.0.1
description: My pubspec file.
''');
    addSource('/testName/lib/myLib.dart', '');
    addSource(
        appPath,
        '''
import 'package:testName/myLib.dart';
export 'package:testName/myLib.dart';
''');
    // configure Uri resolves
    context.sourceFactory = new SourceFactory([
      AbstractContextTest.SDK_RESOLVER,
      new PackageMapUriResolver(provider, <String, List<Folder>>{
        'testName': [provider.getResource('/testName/lib')]
      }),
      resourceResolver,
    ]);
    // analyze
    _performAnalysis();
    // perform refactoring
    refactoring = new MoveFileRefactoring(
        provider, searchEngine, context, null, '/testName');
    refactoring.newFile = '/newName';
    await _assertSuccessfulRefactoring();
    assertFileChangeResult(
        pubspecPath,
        '''
name: newName
version: 0.0.1
description: My pubspec file.
''');
    assertFileChangeResult(
        appPath,
        '''
import 'package:newName/myLib.dart';
export 'package:newName/myLib.dart';
''');
  }

  /**
   * Checks that all conditions are OK.
   */
  Future _assertSuccessfulRefactoring() async {
    await assertRefactoringConditionsOK();
    refactoringChange = await refactoring.createChange();
  }

  void _createRefactoring(String newName) {
    refactoring = new MoveFileRefactoring(
        provider, searchEngine, context, testSource, null);
    refactoring.newFile = newName;
  }

  void _performAnalysis() {
    while (true) {
      AnalysisResult result = context.performAnalysisTask();
      if (!result.hasMoreWork) {
        break;
      }
      for (ChangeNotice notice in result.changeNotices) {
        if (notice.source.fullName.startsWith('/project/')) {
          index.indexUnit(context, notice.resolvedDartUnit);
        }
      }
    }
  }
}
