// 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 'dart:async';

import 'package:analysis_server/src/services/correction/status.dart';
import 'package:analysis_server/src/services/refactoring/refactoring.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/src/generated/testing/element_search.dart';
import 'package:analyzer_plugin/protocol/protocol_common.dart'
    show RefactoringProblemSeverity, SourceChange;
import 'package:test_reflective_loader/test_reflective_loader.dart';

import 'abstract_refactoring.dart';

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

@reflectiveTest
class ConvertMethodToGetterTest extends RefactoringTest {
  ConvertMethodToGetterRefactoring refactoring;

  test_change_function() async {
    await indexTestUnit('''
int test() => 42;
main() {
  var a = test();
  var b = test();
}
''');
    _createRefactoring('test');
    // apply refactoring
    return _assertSuccessfulRefactoring('''
int get test => 42;
main() {
  var a = test;
  var b = test;
}
''');
  }

  test_change_method() async {
    await indexTestUnit('''
class A {
  int test() => 1;
}
class B extends A {
  int test() => 2;
}
class C extends B {
  int test() => 3;
}
class D extends A {
  int test() => 4;
}
main(A a, B b, C c, D d) {
  var va = a.test();
  var vb = b.test();
  var vc = c.test();
  var vd = d.test();
}
''');
    _createRefactoringForString('test() => 2');
    // apply refactoring
    return _assertSuccessfulRefactoring('''
class A {
  int get test => 1;
}
class B extends A {
  int get test => 2;
}
class C extends B {
  int get test => 3;
}
class D extends A {
  int get test => 4;
}
main(A a, B b, C c, D d) {
  var va = a.test;
  var vb = b.test;
  var vc = c.test;
  var vd = d.test;
}
''');
  }

  test_change_multipleFiles() async {
    await indexUnit(
        '/other.dart',
        r'''
class A {
  int test() => 1;
}
''');
    await indexTestUnit('''
import 'other.dart';
class B extends A {
  int test() => 2;
}
main(A a, B b) {
  a.test();
  b.test();
}
''');
    _createRefactoringForString('test() => 2');
    // apply refactoring
    return _assertSuccessfulRefactoring('''
import 'other.dart';
class B extends A {
  int get test => 2;
}
main(A a, B b) {
  a.test;
  b.test;
}
''');
  }

  test_checkInitialConditions_alreadyGetter() async {
    await indexTestUnit('''
int get test => 42;
main() {
  var a = test;
  var b = test;
}
''');
    ExecutableElement element = findElement('test', ElementKind.GETTER);
    _createRefactoringForElement(element);
    // check conditions
    _assertInitialConditions_fatal(
        'Only class methods or top-level functions can be converted to getters.');
  }

  test_checkInitialConditions_hasParameters() async {
    await indexTestUnit('''
int test(x) => x * 2;
main() {
  var v = test(1);
}
''');
    _createRefactoring('test');
    // check conditions
    _assertInitialConditions_fatal(
        'Only methods without parameters can be converted to getters.');
  }

  test_checkInitialConditions_localFunction() async {
    await indexTestUnit('''
main() {
  test() {}
  var v = test();
}
''');
    ExecutableElement element = findElementsByName(testUnit, 'test').single;
    _createRefactoringForElement(element);
    // check conditions
    _assertInitialConditions_fatal(
        'Only top-level functions can be converted to getters.');
  }

  test_checkInitialConditions_notFunctionOrMethod() async {
    await indexTestUnit('''
class A {
  A.test();
}
''');
    _createRefactoring('test');
    // check conditions
    _assertInitialConditions_fatal(
        'Only class methods or top-level functions can be converted to getters.');
  }

  test_checkInitialConditions_returnTypeVoid() async {
    await indexTestUnit('''
void test() {}
''');
    _createRefactoring('test');
    // check conditions
    _assertInitialConditions_fatal('Cannot convert function returning void.');
  }

  Future _assertInitialConditions_fatal(String message) async {
    RefactoringStatus status = await refactoring.checkInitialConditions();
    assertRefactoringStatus(status, RefactoringProblemSeverity.FATAL,
        expectedMessage: message);
  }

  /**
   * Checks that all conditions are OK and the result of applying the [Change]
   * to [testUnit] is [expectedCode].
   */
  Future _assertSuccessfulRefactoring(String expectedCode) async {
    await assertRefactoringConditionsOK();
    SourceChange refactoringChange = await refactoring.createChange();
    this.refactoringChange = refactoringChange;
    assertTestChangeResult(expectedCode);
  }

  void _createRefactoring(String elementName) {
    ExecutableElement element = findElement(elementName);
    _createRefactoringForElement(element);
  }

  void _createRefactoringForElement(ExecutableElement element) {
    refactoring = new ConvertMethodToGetterRefactoring(
        searchEngine, astProvider, element);
  }

  void _createRefactoringForString(String search) {
    ExecutableElement element = findNodeElementAtString(search);
    _createRefactoringForElement(element);
  }
}
