// Copyright (c) 2015, 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/src/lint/pub.dart';
import 'package:source_span/source_span.dart';
import 'package:test/test.dart';

main() {
  defineTests();
}

defineTests() {
  const src = """
name: linter
version: 0.0.1
author: Dart Team <misc@dartlang.org>
authors:
  - Bill
  - Ted
description: Style linter for Dart.
documentation:
homepage: https://github.com/dart-lang/linter
dependencies:
  transmogrify:
    hosted:
      name: transmogrify
      url: http://your-package-server.com
    version: '>=0.4.0 <1.0.0'
  analyzer: '0.24.0-dev.1'
  cli_util: '>=0.0.1 <0.1.0'
  semver: '>=0.2.0 <0.3.0'
  yaml: '>=2.1.2 <3.0.0'
  kittens:
    git:
      url: git://github.com/munificent/kittens.git
      ref: some-branch
  foo: any
dev_dependencies:
  markdown: '>=0.7.1+2 <0.8.0'
  unittest: '>=0.11.0 <0.12.0'
""";

  Pubspec ps = new Pubspec.parse(src);

  group('pubspec', () {
    group('basic', () {
      test('toString()', () {
        // For now just confirm it doesn't blow up
        expect(ps.toString(), isNotNull);
      });
    });
    group('entries', () {
      testValue('name', ps.name, equals('linter'));
      testKeySpan('name', ps.name, startOffset: 0, endOffset: 4);
      testValueSpan('name', ps.name, startOffset: 6, endOffset: 12);
      group('documentation', () {
        test('no value', () {
          expect(ps.documentation.value.text, isNull);
        });
      });
      testValue('homepage', ps.homepage,
          equals('https://github.com/dart-lang/linter'));
      testValue(
          'description', ps.description, equals('Style linter for Dart.'));
      testValue('version', ps.version, equals('0.0.1'));
      testValue('author', ps.author, equals('Dart Team <misc@dartlang.org>'));

      group('authors', () {
        PSNodeList authors = ps.authors;
        test('contents', () {
          expect(authors, isNotNull);
          expect(authors.any((PSNode n) => n.text == 'Bill'), isTrue);
          expect(authors.any((PSNode n) => n.text == 'Ted'), isTrue);
        });
      });

      testDepListContains('dependencies', ps.dependencies, [
        {'analyzer': '0.24.0-dev.1'}
      ]);

      testDepListContains('dev_dependencies', ps.devDependencies, [
        {'markdown': '>=0.7.1+2 <0.8.0'}
      ]);

      group('hosted', () {
        PSDependency dep =
            findDependency(ps.dependencies, name: 'transmogrify');
        PSHost host = dep.host;
        testValue('name', host.name, equals('transmogrify'));
        testValue('url', host.url, equals('http://your-package-server.com'));
        testKeySpan('name', host.name, startOffset: 237, endOffset: 241);
        testValueSpan('name', host.name, startOffset: 243, endOffset: 255);
      });

      group('git', () {
        PSDependency dep = findDependency(ps.dependencies, name: 'kittens');
        PSGitRepo git = dep.git;
        testValue('ref', git.ref, equals('some-branch'));
        testValue(
            'url', git.url, equals('git://github.com/munificent/kittens.git'));
      });
    });
//    group('visiting', () {
//      test('smoke', () {
//        var mock = new MockPubVisitor();
//        ps.accept(mock);
//        verify(mock.visitPackageAuthor(any)).called(1);
//        verify(mock.visitPackageAuthors(any)).called(1);
//        verify(mock.visitPackageDependencies(any)).called(1);
//        verify(mock.visitPackageDependency(any)).called(7);
//        verify(mock.visitPackageDescription(any)).called(1);
//        verify(mock.visitPackageDevDependencies(any)).called(1);
//        verify(mock.visitPackageDevDependency(any)).called(2);
//        verify(mock.visitPackageDocumentation(any)).called(1);
//        verify(mock.visitPackageHomepage(any)).called(1);
//        verify(mock.visitPackageName(any)).called(1);
//        verify(mock.visitPackageVersion(any)).called(1);
//      });
//    });
    // TODO(brianwilkerson) Rewrite this to use a memory resource provider.
//    group('initialization', () {
//      test('sourceUrl', () {
//        File ps = new File('test/_data/p1/_pubspec.yaml');
//        Pubspec spec = new Pubspec.parse(ps.readAsStringSync(),
//            sourceUrl: p.toUri(ps.path));
//        expect(spec.name.key.span.sourceUrl.toFilePath(windows: false),
//            equals('test/_data/p1/_pubspec.yaml'));
//      });
//    });
//    group('parsing', () {
//      test('bad yaml', () {
//        File ps = new File('test/_data/p3/_pubspec.yaml');
//        Pubspec spec = new Pubspec.parse(ps.readAsStringSync(),
//            sourceUrl: p.toUri(ps.path));
//        expect(spec.name, isNull);
//        expect(spec.description, isNull);
//      });
//    });
  });
}

PSDependency findDependency(PSDependencyList deps, {String name}) =>
    deps.firstWhere((dep) => dep.name.text == name, orElse: () => null);

testDepListContains(
    String label, PSDependencyList list, List<Map<String, String>> exp) {
  test(label, () {
    exp.forEach((Map<String, String> entry) {
      entry.forEach((k, v) {
        PSDependency dep = findDependency(list, name: k);
        expect(dep, isNotNull);
        expect(dep.version.value.text, equals(v));
      });
    });
  });
}

testEntry(String label, PSEntry node, Matcher m) {
  group(label, () {
    test('entry', () {
      expect(node, m);
    });
  });
}

testKeySpan(String label, PSEntry node, {int startOffset, int endOffset}) {
  group(label, () {
    group('key', () {
      testSpan(node.key.span, startOffset: startOffset, endOffset: endOffset);
    });
  });
}

testSpan(SourceSpan span, {int startOffset, int endOffset}) {
  test('span', () {
    var start = span.start;
    expect(start, isNotNull);
    expect(start.offset, equals(startOffset));
    var end = span.end;
    expect(end, isNotNull);
    expect(end.offset, equals(endOffset));
  });
}

testValue(String label, PSEntry node, Matcher m) {
  group(label, () {
    test('value', () {
      expect(node.value.text, m);
    });
  });
}

testValueSpan(String label, PSEntry node, {int startOffset, int endOffset}) {
  group(label, () {
    group('value', () {
      testSpan(node.value.span, startOffset: startOffset, endOffset: endOffset);
    });
  });
}
