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