'use strict';

var Curry = require("./curry.js");
var Caml_option = require("./caml_option.js");
var Belt_internalAVLtree = require("./belt_internalAVLtree.js");
var Belt_internalMapString = require("./belt_internalMapString.js");

function set(t, newK, newD) {
  if (t === null) {
    return Belt_internalAVLtree.singleton(newK, newD);
  }
  var k = t.key;
  if (newK === k) {
    return Belt_internalAVLtree.updateValue(t, newD);
  }
  var v = t.value;
  if (newK < k) {
    return Belt_internalAVLtree.bal(set(t.left, newK, newD), k, v, t.right);
  } else {
    return Belt_internalAVLtree.bal(t.left, k, v, set(t.right, newK, newD));
  }
}

function updateU(t, x, f) {
  if (t !== null) {
    var k = t.key;
    if (x === k) {
      var match = f(Caml_option.some(t.value));
      if (match !== undefined) {
        return Belt_internalAVLtree.updateValue(t, Caml_option.valFromOption(match));
      }
      var l = t.left;
      var r = t.right;
      if (l === null) {
        return r;
      }
      if (r === null) {
        return l;
      }
      var kr = {
        contents: r.key
      };
      var vr = {
        contents: r.value
      };
      var r$1 = Belt_internalAVLtree.removeMinAuxWithRef(r, kr, vr);
      return Belt_internalAVLtree.bal(l, kr.contents, vr.contents, r$1);
    }
    var v = t.value;
    var l$1 = t.left;
    var r$2 = t.right;
    if (x < k) {
      var ll = updateU(l$1, x, f);
      if (l$1 === ll) {
        return t;
      } else {
        return Belt_internalAVLtree.bal(ll, k, v, r$2);
      }
    }
    var rr = updateU(r$2, x, f);
    if (r$2 === rr) {
      return t;
    } else {
      return Belt_internalAVLtree.bal(l$1, k, v, rr);
    }
  }
  var match$1 = f(undefined);
  if (match$1 !== undefined) {
    return Belt_internalAVLtree.singleton(x, Caml_option.valFromOption(match$1));
  } else {
    return t;
  }
}

function update(t, x, f) {
  return updateU(t, x, Curry.__1(f));
}

function removeAux(n, x) {
  var v = n.key;
  var l = n.left;
  var r = n.right;
  if (x === v) {
    if (l === null) {
      return r;
    }
    if (r === null) {
      return l;
    }
    var kr = {
      contents: r.key
    };
    var vr = {
      contents: r.value
    };
    var r$1 = Belt_internalAVLtree.removeMinAuxWithRef(r, kr, vr);
    return Belt_internalAVLtree.bal(l, kr.contents, vr.contents, r$1);
  }
  if (x < v) {
    if (l === null) {
      return n;
    }
    var ll = removeAux(l, x);
    if (ll === l) {
      return n;
    } else {
      return Belt_internalAVLtree.bal(ll, v, n.value, r);
    }
  }
  if (r === null) {
    return n;
  }
  var rr = removeAux(r, x);
  return Belt_internalAVLtree.bal(l, v, n.value, rr);
}

function remove(n, x) {
  if (n !== null) {
    return removeAux(n, x);
  } else {
    return null;
  }
}

function removeMany(t, keys) {
  var len = keys.length;
  if (t !== null) {
    var _t = t;
    var _i = 0;
    while(true) {
      var i = _i;
      var t$1 = _t;
      if (i >= len) {
        return t$1;
      }
      var ele = keys[i];
      var u = removeAux(t$1, ele);
      if (u === null) {
        return u;
      }
      _i = i + 1 | 0;
      _t = u;
      continue ;
    };
  } else {
    return null;
  }
}

function mergeMany(h, arr) {
  var len = arr.length;
  var v = h;
  for(var i = 0 ,i_finish = len - 1 | 0; i <= i_finish; ++i){
    var match = arr[i];
    v = set(v, match[0], match[1]);
  }
  return v;
}

var empty = null;

var isEmpty = Belt_internalAVLtree.isEmpty;

var has = Belt_internalMapString.has;

var cmpU = Belt_internalMapString.cmpU;

var cmp = Belt_internalMapString.cmp;

var eqU = Belt_internalMapString.eqU;

var eq = Belt_internalMapString.eq;

var findFirstByU = Belt_internalAVLtree.findFirstByU;

var findFirstBy = Belt_internalAVLtree.findFirstBy;

var forEachU = Belt_internalAVLtree.forEachU;

var forEach = Belt_internalAVLtree.forEach;

var reduceU = Belt_internalAVLtree.reduceU;

var reduce = Belt_internalAVLtree.reduce;

var everyU = Belt_internalAVLtree.everyU;

var every = Belt_internalAVLtree.every;

var someU = Belt_internalAVLtree.someU;

var some = Belt_internalAVLtree.some;

var size = Belt_internalAVLtree.size;

var toList = Belt_internalAVLtree.toList;

var toArray = Belt_internalAVLtree.toArray;

var fromArray = Belt_internalMapString.fromArray;

var keysToArray = Belt_internalAVLtree.keysToArray;

var valuesToArray = Belt_internalAVLtree.valuesToArray;

var minKey = Belt_internalAVLtree.minKey;

var minKeyUndefined = Belt_internalAVLtree.minKeyUndefined;

var maxKey = Belt_internalAVLtree.maxKey;

var maxKeyUndefined = Belt_internalAVLtree.maxKeyUndefined;

var minimum = Belt_internalAVLtree.minimum;

var minUndefined = Belt_internalAVLtree.minUndefined;

var maximum = Belt_internalAVLtree.maximum;

var maxUndefined = Belt_internalAVLtree.maxUndefined;

var get = Belt_internalMapString.get;

var getUndefined = Belt_internalMapString.getUndefined;

var getWithDefault = Belt_internalMapString.getWithDefault;

var getExn = Belt_internalMapString.getExn;

var checkInvariantInternal = Belt_internalAVLtree.checkInvariantInternal;

var mergeU = Belt_internalMapString.mergeU;

var merge = Belt_internalMapString.merge;

var keepU = Belt_internalAVLtree.keepSharedU;

var keep = Belt_internalAVLtree.keepShared;

var partitionU = Belt_internalAVLtree.partitionSharedU;

var partition = Belt_internalAVLtree.partitionShared;

var split = Belt_internalMapString.split;

var mapU = Belt_internalAVLtree.mapU;

var map = Belt_internalAVLtree.map;

var mapWithKeyU = Belt_internalAVLtree.mapWithKeyU;

var mapWithKey = Belt_internalAVLtree.mapWithKey;

exports.empty = empty;
exports.isEmpty = isEmpty;
exports.has = has;
exports.cmpU = cmpU;
exports.cmp = cmp;
exports.eqU = eqU;
exports.eq = eq;
exports.findFirstByU = findFirstByU;
exports.findFirstBy = findFirstBy;
exports.forEachU = forEachU;
exports.forEach = forEach;
exports.reduceU = reduceU;
exports.reduce = reduce;
exports.everyU = everyU;
exports.every = every;
exports.someU = someU;
exports.some = some;
exports.size = size;
exports.toList = toList;
exports.toArray = toArray;
exports.fromArray = fromArray;
exports.keysToArray = keysToArray;
exports.valuesToArray = valuesToArray;
exports.minKey = minKey;
exports.minKeyUndefined = minKeyUndefined;
exports.maxKey = maxKey;
exports.maxKeyUndefined = maxKeyUndefined;
exports.minimum = minimum;
exports.minUndefined = minUndefined;
exports.maximum = maximum;
exports.maxUndefined = maxUndefined;
exports.get = get;
exports.getUndefined = getUndefined;
exports.getWithDefault = getWithDefault;
exports.getExn = getExn;
exports.checkInvariantInternal = checkInvariantInternal;
exports.remove = remove;
exports.removeMany = removeMany;
exports.set = set;
exports.updateU = updateU;
exports.update = update;
exports.mergeU = mergeU;
exports.merge = merge;
exports.mergeMany = mergeMany;
exports.keepU = keepU;
exports.keep = keep;
exports.partitionU = partitionU;
exports.partition = partition;
exports.split = split;
exports.mapU = mapU;
exports.map = map;
exports.mapWithKeyU = mapWithKeyU;
exports.mapWithKey = mapWithKey;
/* No side effect */