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

// @dart = 2.9

import 'dart:collection';
import 'dart:html';
import 'dart:svg' as svg;

import "package:expect/expect.dart";
import 'package:expect/minitest.dart';

// Test for `querySelectorAll(xxx).classes.op()` where the query returns mixed
// Html and Svg elements.

Element makeElementsContainer() {
  var e = new Element.html('<ul class="yes foo">'
      '<li class="yes quux qux">'
      '</ul>');
  final svgContent = r"""
<svg version="1.1">
  <circle class="yes qux"></circle>
  <path class="yes classy"></path>
</svg>""";
  final svgElement = new svg.SvgElement.svg(svgContent);
  e.append(svgElement);
  return e;
}

Element elementsContainer;

/// Test top-level querySelectorAll with generics.
topLevelQuerySelector() {
  var noElementsTop = querySelectorAll<svg.PathElement>('.no');
  expect(noElementsTop.length, 0);
  expect(noElementsTop is List, true);

  // Expect runtime error all elements in the list are not the proper type.
  Expect.throwsAssertionError(() => querySelectorAll<svg.CircleElement>('path'),
      'All elements not of type CircleElement');

  var simpleElems = querySelectorAll('circle');
  expect(simpleElems.length, 1);
  expect(simpleElems is List, true);
  expect(simpleElems is List<dynamic>, true);
  expect(simpleElems is List<svg.CircleElement>, false);
  expect(simpleElems[0] is svg.CircleElement, true);

  var varElementsFromTop = querySelectorAll<svg.CircleElement>('circle');
  expect(varElementsFromTop.length, 1);
  expect(varElementsFromTop is List, true);
  expect(varElementsFromTop is List<svg.CircleElement>, true);
  expect(varElementsFromTop[0] is svg.CircleElement, true);
  expect(varElementsFromTop is List<svg.PathElement>, false);
  expect(varElementsFromTop[0] is svg.PathElement, false);

  List<svg.CircleElement> elementsFromTop =
      querySelectorAll<svg.CircleElement>('circle');
  expect(elementsFromTop is List, true);
  expect(elementsFromTop is List<svg.CircleElement>, true);
  expect(elementsFromTop[0] is svg.CircleElement, true);
  expect(elementsFromTop.length, 1);
}

ElementList<Element> elementsSetup() {
  elementsContainer = makeElementsContainer();
  document.documentElement.children.add(elementsContainer);
  var elements = document.querySelectorAll('.yes');
  expect(elements.length, 4);

  topLevelQuerySelector();

  return elements;
}

void elementsTearDown() {
  if (elementsContainer != null) {
    document.documentElement.children.remove(elementsContainer);
    elementsContainer = null;
  }
}

/// Returns a canonical string for Set<String> and lists of Element's classes.
String view(var e) {
  if (e is Set) return '${e.toList()..sort()}';
  if (e is Element) return view(e.classes);
  if (e is Iterable) return '${e.map(view).toList()}';
  throw new ArgumentError('Cannot make canonical view string for: $e}');
}

main() {
  Set<String> extractClasses(Element el) {
    final match = new RegExp('class="([^"]+)"').firstMatch(el.outerHtml);
    return new LinkedHashSet.from(match[1].split(' '));
  }

  tearDown(elementsTearDown);

  test('list_view', () {
    // Test that the 'view' helper function is behaving.
    var elements = elementsSetup();
    expect(view(elements.classes), '[classy, foo, quux, qux, yes]');
    expect(view(elements),
        '[[foo, yes], [quux, qux, yes], [qux, yes], [classy, yes]]');
  });

  test('listClasses=', () {
    var elements = elementsSetup();

    elements.classes = ['foo', 'qux'];
    expect(view(elements.classes), '[foo, qux]');
    expect(view(elements), '[[foo, qux], [foo, qux], [foo, qux], [foo, qux]]');

    var elements2 = document.querySelectorAll('.qux');
    expect(view(elements2.classes), '[foo, qux]');
    expect(view(elements2), '[[foo, qux], [foo, qux], [foo, qux], [foo, qux]]');

    for (Element e in elements2) {
      expect(e.classes, equals(['foo', 'qux']));
      expect(extractClasses(e), equals(['foo', 'qux']));
    }

    elements.classes = [];
    expect(view(elements2.classes), '[]');
    expect(view(elements2), '[[], [], [], []]');
  });

  test('listMap', () {
    var elements = elementsSetup();
    expect(elements.classes.map((c) => c.toUpperCase()).toList(),
        unorderedEquals(['YES', 'FOO', 'QUX', 'QUUX', 'CLASSY']));
  });

  test('listContains', () {
    var elements = elementsSetup();
    expect(elements.classes.contains('classy'), isTrue);
    expect(elements.classes.contains('troll'), isFalse);
  });

  test('listAdd', () {
    var elements = elementsSetup();
    var added = elements.classes.add('lassie');
    expect(added, isFalse);

    expect(view(elements.classes), '[classy, foo, lassie, quux, qux, yes]');
    expect(
        view(elements),
        '[[foo, lassie, yes], [lassie, quux, qux, yes], '
        '[lassie, qux, yes], [classy, lassie, yes]]');
  });

  test('listRemove', () {
    var elements = elementsSetup();
    expect(elements.classes.remove('lassi'), isFalse);
    expect(view(elements.classes), '[classy, foo, quux, qux, yes]');
    expect(view(elements),
        '[[foo, yes], [quux, qux, yes], [qux, yes], [classy, yes]]');

    expect(elements.classes.remove('qux'), isTrue);
    expect(view(elements.classes), '[classy, foo, quux, yes]');
    expect(view(elements), '[[foo, yes], [quux, yes], [yes], [classy, yes]]');
  });

  test('listToggle', () {
    var elements = elementsSetup();
    elements.classes.toggle('qux');
    expect(view(elements.classes), '[classy, foo, quux, qux, yes]');
    expect(view(elements),
        '[[foo, qux, yes], [quux, yes], [yes], [classy, qux, yes]]');
  });

  test('listAddAll', () {
    var elements = elementsSetup();
    elements.classes.addAll(['qux', 'lassi', 'sassy']);
    expect(
        view(elements.classes), '[classy, foo, lassi, quux, qux, sassy, yes]');
    expect(
        view(elements),
        '[[foo, lassi, qux, sassy, yes], [lassi, quux, qux, sassy, yes], '
        '[lassi, qux, sassy, yes], [classy, lassi, qux, sassy, yes]]');
  });

  test('listRemoveAll', () {
    var elements = elementsSetup();
    elements.classes.removeAll(['qux', 'classy', 'mumble']);
    expect(view(elements.classes), '[foo, quux, yes]');
    expect(view(elements), '[[foo, yes], [quux, yes], [yes], [yes]]');

    elements.classes.removeAll(['foo', 'yes']);
    expect(view(elements.classes), '[quux]');
    expect(view(elements), '[[], [quux], [], []]');
  });

  test('listToggleAll', () {
    var elements = elementsSetup();
    elements.classes.toggleAll(['qux', 'mornin']);
    expect(view(elements.classes), '[classy, foo, mornin, quux, qux, yes]');
    expect(
        view(elements),
        '[[foo, mornin, qux, yes], [mornin, quux, yes], '
        '[mornin, yes], [classy, mornin, qux, yes]]');
  });

  test('listRetainAll', () {
    var elements = elementsSetup();
    elements.classes.retainAll(['bar', 'baz', 'classy', 'qux']);
    expect(view(elements.classes), '[classy, qux]');
    expect(view(elements), '[[], [qux], [qux], [classy]]');
  });

  test('listRemoveWhere', () {
    var elements = elementsSetup();
    elements.classes.removeWhere((s) => s.startsWith('q'));
    expect(view(elements.classes), '[classy, foo, yes]');
    expect(view(elements), '[[foo, yes], [yes], [yes], [classy, yes]]');
  });

  test('listRetainWhere', () {
    var elements = elementsSetup();
    elements.classes.retainWhere((s) => s.startsWith('q'));
    expect(view(elements.classes), '[quux, qux]');
    expect(view(elements), '[[], [quux, qux], [qux], []]');
  });

  test('listContainsAll', () {
    var elements = elementsSetup();
    expect(elements.classes.containsAll(['qux', 'mornin']), isFalse);
    expect(elements.classes.containsAll(['qux', 'classy']), isTrue);
  });
}
