// 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 '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, isNull);

    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);
  });
}
