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