// Copyright (c) 2016, 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.
//
// DartOptions=--generic-method-syntax

/// Dart test verifying that the parser can handle type parameterization of
/// method declarations and method invocations. Slightly adjusted version of
/// code from DEP #22.

library generic_methods_test;

import "package:expect/expect.dart";

class BinaryTreeNode<K extends Comparable<K>, V> {
  final K _key;
  final V _value;
  final BinaryTreeNode<K, V> _left;
  final BinaryTreeNode<K, V> _right;

  BinaryTreeNode(this._key, this._value,
      {BinaryTreeNode<K, V> left: null, BinaryTreeNode<K, V> right: null}) :
          _left = left, _right = right;

  // Use fresh type variables.
  static BinaryTreeNode<K2, V2> insertOpt<K2 extends Comparable<K2>, V2>(
      BinaryTreeNode<K2, V2> t, K2 key, V2 value) {
    return (t == null) ? new BinaryTreeNode(key, value) : t.insert(key, value);
  }

  BinaryTreeNode<K, V> insert(K key, V value) {
    int c = key.compareTo(_key);
    if (c == 0) return this;
    var _insert = (BinaryTreeNode<K, V> node, K key, V value) =>
        insertOpt<K, V>(node, key, value);
    BinaryTreeNode<K, V> left = _left;
    BinaryTreeNode<K, V> right = _right;
    if (c < 0) {
      left = _insert(_left, key, value);
    } else {
      right = _insert(_right, key, value);
    }
    return new BinaryTreeNode<K, V>(_key, _value, left: left, right: right);
  }

  // Reuse type variables [K], [V] to test shadowing.
  static BinaryTreeNode<K, U> mapOpt<K extends Comparable<K>, V, U>
      (BinaryTreeNode<K, V> t, U f(V x)) {
    return (t == null) ? null : t.map<U>(f);
  }

  BinaryTreeNode<K, U> map<U>(U f(V x)){
    var _map = (BinaryTreeNode<K, V> t, U f(V x)) => mapOpt<K, V, U>(t, f);
    return new BinaryTreeNode<K, U>(
        _key,
        f(_value),
        left: _map(_left, f),
        right: _map(_right, f));
  }

  // Use fresh [K2], shadowing [V].
  static S foldPreOpt<K2 extends Comparable<K2>, V, S>(
      BinaryTreeNode<K2, V> t, S init, S f(V t, S s)) {
    return (t == null) ? init : t.foldPre<S>(init, f);
  }

  S foldPre<S>(S init, S f(V t, S s)) {
    var _fold = (BinaryTreeNode<K, V> t, S s, S f(V t, S s)) =>
        foldPreOpt<K, V, S>(t, s, f);
    S s = init;
    s = f(_value, s);
    s = _fold(_left, s, f);
    s = _fold(_right, s, f);
    return s;
  }
}

class BinaryTree<K extends Comparable<K>, V> {
  final BinaryTreeNode<K, V> _root;

  BinaryTree._internal(this._root);
  BinaryTree.empty() : this._internal(null);

  BinaryTree<K, V> insert(K key, V value) {
    BinaryTreeNode<K, V> root =
        BinaryTreeNode.insertOpt<K, V>(_root, key, value);
    return new BinaryTree<K, V>._internal(root);
  }

  BinaryTree<K, U> map<U>(U f(V x)) {
    BinaryTreeNode<K, U> root = BinaryTreeNode.mapOpt<K, V, U>(_root, f);
    return new BinaryTree<K, U>._internal(root);
  }

  S foldPre<S>(S init, S f(V t, S s)) {
    return BinaryTreeNode.foldPreOpt<K, V, S>(_root, init, f);
  }
}

main() {
  BinaryTree<num, String> sT = new BinaryTree<num, String>.empty();

  sT = sT.insert(0, "");
  sT = sT.insert(1, " ");
  sT = sT.insert(2, "  ");
  sT = sT.insert(3, "   ");

  BinaryTree<num, num> iT = sT.map<num>((String s) => s.length);

  Expect.equals(iT.foldPre<num>(0, (int i, num s) => i + s), 6);
}
