// Copyright (c) 2013, 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.

library created_callback_test;

import 'dart:html';
import 'dart:js' as js;

import 'package:unittest/unittest.dart';

import 'utils.dart';

class A extends HtmlElement {
  static final tag = 'x-a';
  factory A() => new Element.tag(tag);
  A.created() : super.created() {
    createdInvocations++;
  }

  static int createdInvocations = 0;
}

class B extends HtmlElement {
  static final tag = 'x-b';
  factory B() => new Element.tag(tag);
  B.created() : super.created();
}

class C extends HtmlElement {
  static final tag = 'x-c';
  factory C() => new Element.tag(tag);
  C.created() : super.created() {
    createdInvocations++;

    if (this.id != 'u') {
      return;
    }

    var t = div.querySelector('#t');
    var v = div.querySelector('#v');
    var w = div.querySelector('#w');

    expect(querySelector('x-b:not(:unresolved)'), this);
    expect(querySelectorAll(':unresolved'), [v, w]);

    // As per:
    // http://www.w3.org/TR/2013/WD-custom-elements-20130514/#serializing-and-parsing
    // creation order is t, u, v, w (postorder).
    expect(t is C, isTrue);
    // Note, this is different from JavaScript where this would be false.
    expect(v is C, isTrue);
  }

  static int createdInvocations = 0;
  static var div;
}

main() {
  // Adapted from Blink's
  // fast/dom/custom/created-callback test.

  var registered = false;
  setUp(() {
    return customElementsReady.then((_) {
      if (!registered) {
        registered = true;
        document.registerElement2(B.tag, {'prototype': B});
        document.registerElement2(C.tag, {'prototype': C});
        ErrorConstructorElement.register();
      }
    });
  });

  test('transfer created callback', () {
    document.registerElement2(A.tag, {'prototype': A as dynamic});
    var x = new A();
    expect(A.createdInvocations, 1);
  });

  test('unresolved and created callback timing', () {
    var div = new DivElement();
    C.div = div;
    div.setInnerHtml("""
<x-c id="t"></x-c>
<x-b id="u"></x-b>
<x-c id="v"></x-c>
<x-b id="w"></x-b>
""", treeSanitizer: NodeTreeSanitizer.trusted);

    upgradeCustomElements(div);

    expect(C.createdInvocations, 2);
    expect(div.querySelector('#w') is B, isTrue);
  });

  test('nesting of constructors', NestedElement.test);

  test('access while upgrading gets unupgraded element',
      AccessWhileUpgradingElement.test);

  test('cannot call created constructor', () {
    expect(() {
      new B.created();
    }, throws);
  });

  test('cannot register without created', () {
    expect(() {
      document.registerElement2(
          MissingCreatedElement.tag, {'prototype': MissingCreatedElement});
    }, throws);
  });

  test('throw on createElement does not upgrade', () {
    ErrorConstructorElement.callCount = 0;

    var e;
    expectGlobalError(() {
      e = new Element.tag(ErrorConstructorElement.tag);
    });
    expect(ErrorConstructorElement.callCount, 1);
    expect(e is HtmlElement, isTrue);
    expect(e is ErrorConstructorElement, isFalse);

    var dummy = new DivElement();
    dummy.append(e);
    e = dummy.firstChild;
    expect(ErrorConstructorElement.callCount, 1);
  });

  test('throw on innerHtml does not upgrade', () {
    ErrorConstructorElement.callCount = 0;

    var dummy = new DivElement();
    var tag = ErrorConstructorElement.tag;
    expectGlobalError(() {
      dummy.setInnerHtml('<$tag></$tag>',
          treeSanitizer: NodeTreeSanitizer.trusted);
    });

    expect(ErrorConstructorElement.callCount, 1);

    var e = dummy.firstChild;
    // Accessing should not re-run the constructor.
    expect(ErrorConstructorElement.callCount, 1);
    expect(e is HtmlElement, isTrue);
    expect(e is ErrorConstructorElement, isFalse);
  });

  test('cannot register created with params', () {
    expect(() {
      document.registerElement2(
          'x-created-with-params', {'prototype': CreatedWithParametersElement});
    }, throws);
  });

  test('created cannot be called from nested constructor',
      NestedCreatedConstructorElement.test);

  // TODO(vsm): Port additional test from upstream here:
  // http://src.chromium.org/viewvc/blink/trunk/LayoutTests/fast/dom/custom/created-callback.html?r1=156141&r2=156185
}

class NestedElement extends HtmlElement {
  static final tag = 'x-nested';

  final Element b = new B();

  factory NestedElement() => new Element.tag(tag);
  NestedElement.created() : super.created();

  static void register() {
    document.registerElement2(tag, {'prototype': NestedElement});
  }

  static void test() {
    register();

    var e = new NestedElement();
    expect(e.b, isNotNull);
    expect(e.b is B, isTrue);
    expect(e is NestedElement, isTrue);
  }
}

class AccessWhileUpgradingElement extends HtmlElement {
  static final tag = 'x-access-while-upgrading';

  static Element upgradingContext;
  static Element upgradingContextChild;

  final foo = runInitializerCode();

  factory AccessWhileUpgradingElement() => new Element.tag(tag);
  AccessWhileUpgradingElement.created() : super.created();

  static runInitializerCode() {
    upgradingContextChild = upgradingContext.firstChild;

    return 666;
  }

  static void register() {
    document.registerElement2(tag, {'prototype': AccessWhileUpgradingElement});
  }

  static void test() {
    register();

    upgradingContext = new DivElement();
    upgradingContext.setInnerHtml('<$tag></$tag>',
        treeSanitizer: new NullTreeSanitizer());
    dynamic child = upgradingContext.firstChild;

    expect(child.foo, 666);
    expect(upgradingContextChild is HtmlElement, isFalse);
    expect(upgradingContextChild is AccessWhileUpgradingElement, isFalse,
        reason: 'Elements accessed while upgrading should not be upgraded.');
  }
}

class MissingCreatedElement extends HtmlElement {
  static final tag = 'x-missing-created';

  factory MissingCreatedElement() => new Element.tag(tag);
}

class ErrorConstructorElement extends HtmlElement {
  static final tag = 'x-throws-in-constructor';
  static int callCount = 0;

  factory ErrorConstructorElement() => new Element.tag(tag);

  ErrorConstructorElement.created() : super.created() {
    ++callCount;
    throw new Exception('Just messin with ya');
  }

  static void register() {
    document.registerElement2(tag, {'prototype': ErrorConstructorElement});
  }
}

class NestedCreatedConstructorElement extends HtmlElement {
  static final tag = 'x-nested-created-constructor';

  // Should not be able to call this here.
  final B b = constructB();
  static B constructedB;

  factory NestedCreatedConstructorElement() => new Element.tag(tag);
  NestedCreatedConstructorElement.created() : super.created();

  static void register() {
    document
        .registerElement2(tag, {'prototype': NestedCreatedConstructorElement});
  }

  // Try to run the created constructor, and record the results.
  static constructB() {
    // This should throw an exception.
    constructedB = new B.created();
    return constructedB;
  }

  static void test() {
    register();

    // Exception should have occurred on upgrade.
    var e;
    expectGlobalError(() {
      e = new Element.tag(tag);
    });
    expect(e is NestedCreatedConstructorElement, isFalse);
    expect(e is HtmlElement, isTrue);
    // Should not have been set.
    expect(constructedB, isNull);
  }
}

class CreatedWithParametersElement extends HtmlElement {
  CreatedWithParametersElement.created(ignoredParam) : super.created();
}

void expectGlobalError(Function test) {
  js.context['testExpectsGlobalError'] = true;
  try {
    test();
  } catch (e) {
    rethrow;
  } finally {
    js.context['testExpectsGlobalError'] = false;
  }
  var errors = js.context['testSuppressedGlobalErrors'];
  expect(errors['length'], 1);
  // Clear out the errors;
  js.context['testSuppressedGlobalErrors']['length'] = 0;
}
