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

/// Dart test verifying that the parser can handle type parameterization of
/// function declarations and function invocations. Variant of code from
/// DEP #22, adjusted to use generic top level functions.

library generic_functions_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;

  BinaryTreeNode<K, V> insert(K key, V value) {
    int c = key.compareTo(_key);
    if (c == 0) return this;
    var _insert = (BinaryTreeNode<K, V> t, K key, V value) =>
        insertOpt<K, V>(t, 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);
  }

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

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

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, U> mapOpt<K extends Comparable<K>, V, U>(
    BinaryTreeNode<K, V> t, U f(V x)) {
  return (t == null) ? null : t.map<U>(f);
}

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

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 = 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 = 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 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, (num i, num s) => i + s), 6);
}
