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

/// And end-to-end test that generates code and checks that the output matches
/// the code in `static_test.dart`. Techincally we could run the result in an
/// isolate, but instead we decided to split that up in two tests. This test
/// ensures that we generate the code as it was written in static_test, and
/// separately static_test ensures that the smoke.static library behaves as
/// expected.
library smoke.test.codegen.end_to_end_test;

import 'dart:io';

import 'package:analyzer/src/generated/element.dart';
import 'package:smoke/codegen/generator.dart';
import 'package:smoke/codegen/recorder.dart';
import 'package:unittest/unittest.dart';
import 'package:path/path.dart' as path;

import 'testing_resolver_utils.dart' show initAnalyzer;

main(args) {
  final updateStaticTest = args.length > 0 && args[0] == '--update_static_test';

  test('static_test is up to date', () {
    var scriptPath = path.fromUri(Platform.script);
    var testDir = path.dirname(path.dirname(scriptPath));
    var commonPath = path.join(testDir, 'common.dart');
    var testCode = new File('$commonPath').readAsStringSync();
    var lib = initAnalyzer({'common.dart' : testCode})
        .libraryFor('common.dart');
    var coreLib = lib.visibleLibraries.firstWhere(
        (l) => l.displayName == 'dart.core');
    var generator = new SmokeCodeGenerator();
    var recorder = new Recorder(generator, _resolveImportUrl);

    lookupMember(String className, String memberName, bool recursive) {
      recorder.lookupMember(lib.getType(className), memberName,
          recursive: recursive, includeAccessors: false);
    }

    runQuery(String className, QueryOptions options) {
      recorder.runQuery(lib.getType(className), options,
          includeAccessors: false);
    }

    // Record all getters and setters we use in the tests.
    ['i', 'j', 'j2', 'inc0', 'inc1', 'inc2'].forEach(generator.addGetter);
    ['i', 'j2'].forEach(generator.addSetter);

    // Record static methods used in the tests
    recorder.addStaticMethod(lib.getType('A'), 'staticInc');

    // Record symbol convertions.
    generator.addSymbol('i');

    /// Record all parent-class relations that we explicitly request.
    ['AnnotB', 'A', 'B', 'D', 'H'].forEach(
        (className) => recorder.lookupParent(lib.getType(className)));

    // Record members for which we implicitly request their declaration in
    // has-getter and has-setter tests.
    lookupMember('A', 'i', true);
    lookupMember('A', 'j2', true);
    lookupMember('A', 'inc2', true);
    lookupMember('B', 'a', true);
    lookupMember('B', 'f', true);
    lookupMember('D', 'i', true);
    lookupMember('E', 'y', true);

    // Record also lookups for non-exisiting members.
    lookupMember('B', 'i', true);
    lookupMember('E', 'x', true);
    lookupMember('E', 'z', true);

    // Record members for which we explicitly request their declaration.
    lookupMember('B', 'a', false);
    lookupMember('B', 'w', false);
    lookupMember('A', 'inc1', false);
    lookupMember('F', 'staticMethod', false);
    lookupMember('G', 'b', false);
    lookupMember('G', 'd', false);

    // Lookups from no-such-method test.
    lookupMember('A', 'noSuchMethod', true);
    lookupMember('E', 'noSuchMethod', true);
    lookupMember('E2', 'noSuchMethod', true);

    // Lookups from has-instance-method and has-static-method tests.
    lookupMember('A', 'inc0', true);
    lookupMember('A', 'inc3', true);
    lookupMember('C', 'inc', true);
    lookupMember('D', 'inc', true);
    lookupMember('D', 'inc0', true);
    lookupMember('F', 'staticMethod', true);
    lookupMember('F2', 'staticMethod', true);

    // Record all queries done by the test.
    runQuery('A', new QueryOptions());
    runQuery('D', new QueryOptions(includeInherited: true));

    var vars = lib.definingCompilationUnit.topLevelVariables;
    expect(vars[0].name, 'a1');
    expect(vars[1].name, 'a2');

    runQuery('H', new QueryOptions(includeInherited: true,
        withAnnotations: [vars[0], vars[1], lib.getType('Annot')]));

    var code = _createEntrypoint(generator);
    var staticTestFile = new File(path.join(testDir, 'static_test.dart'));
    var existingCode = staticTestFile.readAsStringSync();
    if (!updateStaticTest) {
      expect(code, existingCode);
    } else if (code == existingCode) {
      print('static_test.dart is already up to date');
    } else {
      staticTestFile.writeAsStringSync(code);
      print('static_test.dart has been updated.');
    }
  });
}

_createEntrypoint(SmokeCodeGenerator generator) {
  var sb = new StringBuffer()
      ..writeln('/// ---- AUTOGENERATED: DO NOT EDIT THIS FILE --------------')
      ..writeln('/// To update this test file, call:')
      ..writeln('/// > dart codegen/end_to_end_test.dart --update_static_test')
      ..writeln('/// --------------------------------------------------------')
      ..writeln('\nlibrary smoke.test.static_test;\n')
      ..writeln("import 'package:unittest/unittest.dart';");

  generator.writeImports(sb);
  sb.writeln("import 'common.dart' as common show main;\n");
  generator.writeTopLevelDeclarations(sb);
  sb.writeln('\n_configure() {');
  generator.writeInitCall(sb);

  sb..writeln('}\n')
      ..writeln('main() {')
      ..writeln('  setUp(_configure);')
      ..writeln('  common.main();')
      ..writeln('}');
  return sb.toString();
}

_resolveImportUrl(LibraryElement lib) {
  if (lib.isDartCore) return 'dart:core';
  if (lib.displayName == 'smoke.test.common') return 'common.dart';
  return 'unknown.dart';
}
