// Copyright (c) 2019, 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:source_span/source_span.dart';
import 'package:term_glyph/term_glyph.dart' as glyph;
import 'package:test/test.dart';

void main() {
  bool oldAscii;
  setUpAll(() {
    oldAscii = glyph.ascii;
    glyph.ascii = true;
  });

  tearDownAll(() {
    glyph.ascii = oldAscii;
  });

  SourceFile file;
  setUp(() {
    file = SourceFile.fromString('''
foo bar baz
whiz bang boom
zip zap zop
fwee fwoo fwip
argle bargle boo
gibble bibble bop
''', url: 'file1.txt');
  });

  test('highlights spans on separate lines', () {
    expect(
        file.span(17, 21).highlightMultiple(
            'one', {file.span(31, 34): 'two', file.span(4, 7): 'three'}),
        equals("""
  ,
1 | foo bar baz
  |     === three
2 | whiz bang boom
  |      ^^^^ one
3 | zip zap zop
  |     === two
  '"""));
  });

  test('highlights spans on the same line', () {
    expect(
        file.span(17, 21).highlightMultiple(
            'one', {file.span(22, 26): 'two', file.span(12, 16): 'three'}),
        equals("""
  ,
2 | whiz bang boom
  |      ^^^^ one
  | ==== three
  |           ==== two
  '"""));
  });

  test('highlights overlapping spans on the same line', () {
    expect(
        file.span(17, 21).highlightMultiple(
            'one', {file.span(20, 26): 'two', file.span(12, 18): 'three'}),
        equals("""
  ,
2 | whiz bang boom
  |      ^^^^ one
  | ====== three
  |         ====== two
  '"""));
  });

  test('highlights multiple multiline spans', () {
    expect(
        file.span(27, 54).highlightMultiple(
            'one', {file.span(54, 89): 'two', file.span(0, 27): 'three'}),
        equals("""
  ,
1 | / foo bar baz
2 | | whiz bang boom
  | '--- three
3 | / zip zap zop
4 | | fwee fwoo fwip
  | '--- one
5 | / argle bargle boo
6 | | gibble bibble bop
  | '--- two
  '"""));
  });

  test('highlights multiple overlapping multiline spans', () {
    expect(
        file.span(12, 70).highlightMultiple(
            'one', {file.span(54, 89): 'two', file.span(0, 27): 'three'}),
        equals("""
  ,
1 | /- foo bar baz
2 | |/ whiz bang boom
  | '+--- three
3 |  | zip zap zop
4 |  | fwee fwoo fwip
5 | /+ argle bargle boo
  | |'--- one
6 | |  gibble bibble bop
  | '---- two
  '"""));
  });

  test('highlights many layers of overlaps', () {
    expect(
        file.span(0, 54).highlightMultiple('one', {
          file.span(12, 77): 'two',
          file.span(27, 84): 'three',
          file.span(39, 88): 'four'
        }),
        equals("""
  ,
1 | /--- foo bar baz
2 | |/-- whiz bang boom
3 | ||/- zip zap zop
4 | |||/ fwee fwoo fwip
  | '+++--- one
5 |  ||| argle bargle boo
6 |  ||| gibble bibble bop
  |  '++------^ two
  |   '+-------------^ three
  |    '--- four
  '"""));
  });

  group("highlights a multiline span that's a subset", () {
    test('with no first or last line overlap', () {
      expect(
          file
              .span(27, 53)
              .highlightMultiple('inner', {file.span(12, 70): 'outer'}),
          equals("""
  ,
2 | /- whiz bang boom
3 | |/ zip zap zop
4 | || fwee fwoo fwip
  | |'--- inner
5 | |  argle bargle boo
  | '---- outer
  '"""));
    });

    test('overlapping the whole first line', () {
      expect(
          file
              .span(12, 53)
              .highlightMultiple('inner', {file.span(12, 70): 'outer'}),
          equals("""
  ,
2 | // whiz bang boom
3 | || zip zap zop
4 | || fwee fwoo fwip
  | |'--- inner
5 | |  argle bargle boo
  | '---- outer
  '"""));
    });

    test('overlapping part of first line', () {
      expect(
          file
              .span(17, 53)
              .highlightMultiple('inner', {file.span(12, 70): 'outer'}),
          equals("""
  ,
2 | /- whiz bang boom
  | |,------^
3 | || zip zap zop
4 | || fwee fwoo fwip
  | |'--- inner
5 | |  argle bargle boo
  | '---- outer
  '"""));
    });

    test('overlapping the whole last line', () {
      expect(
          file
              .span(27, 70)
              .highlightMultiple('inner', {file.span(12, 70): 'outer'}),
          equals("""
  ,
2 | /- whiz bang boom
3 | |/ zip zap zop
4 | || fwee fwoo fwip
5 | || argle bargle boo
  | |'--- inner
  | '---- outer
  '"""));
    });

    test('overlapping part of the last line', () {
      expect(
          file
              .span(27, 66)
              .highlightMultiple('inner', {file.span(12, 70): 'outer'}),
          equals("""
  ,
2 | /- whiz bang boom
3 | |/ zip zap zop
4 | || fwee fwoo fwip
5 | || argle bargle boo
  | |'------------^ inner
  | '---- outer
  '"""));
    });
  });

  group('a single-line span in a multiline span', () {
    test('on the first line', () {
      expect(
          file
              .span(17, 21)
              .highlightMultiple('inner', {file.span(12, 70): 'outer'}),
          equals("""
  ,
2 | / whiz bang boom
  | |      ^^^^ inner
3 | | zip zap zop
4 | | fwee fwoo fwip
5 | | argle bargle boo
  | '--- outer
  '"""));
    });

    test('in the middle', () {
      expect(
          file
              .span(31, 34)
              .highlightMultiple('inner', {file.span(12, 70): 'outer'}),
          equals("""
  ,
2 | / whiz bang boom
3 | | zip zap zop
  | |     ^^^ inner
4 | | fwee fwoo fwip
5 | | argle bargle boo
  | '--- outer
  '"""));
    });

    test('on the last line', () {
      expect(
          file
              .span(60, 66)
              .highlightMultiple('inner', {file.span(12, 70): 'outer'}),
          equals("""
  ,
2 | / whiz bang boom
3 | | zip zap zop
4 | | fwee fwoo fwip
5 | | argle bargle boo
  | |       ^^^^^^ inner
  | '--- outer
  '"""));
    });
  });

  test('highlights multiple files with their URLs', () {
    final file2 = SourceFile.fromString('''
quibble bibble boop
''', url: 'file2.txt');

    expect(
        file.span(31, 34).highlightMultiple('one', {file2.span(8, 14): 'two'}),
        equals("""
  ,--> file1.txt
3 | zip zap zop
  |     ^^^ one
  '
  ,--> file2.txt
1 | quibble bibble boop
  |         ====== two
  '"""));
  });
}
