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