class Hash

def self.[](*objs)

def self.[](*objs)
  `__hash.apply(null, objs)`
end

def self.allocate

def self.allocate
  `__hash()`
end

def self.from_native(obj)

def self.from_native(obj)
  %x{
    var hash = __hash(), map = hash.map;
    for (var key in obj) {
      map[key] = obj[key];
    }
    return hash;
  }
end

def self.new(defaults = undefined, &block)

def self.new(defaults = undefined, &block)
  %x{
    var hash = __hash();
    if (defaults != null) {
      hash.none = defaults;
    }
    else if (block !== nil) {
      hash.proc = block;
    }
    return hash;
  }
end

def ==(other)

def ==(other)
  %x{
    if (#{self} === other) {
      return true;
    }
    if (other.map == null) {
      return false;
    }
    var map  = #{self}.map,
        map2 = other.map;
    for (var key in map) {
      var obj = map[key], obj2 = map2[key];
      if (#{`obj` != `obj2`}) {
        return false;
      }
    }
    return true;
  }
end

def [](key)

def [](key)
  %x{
    var obj = #{self}.map[key];
    if (obj != null) {
      return obj;
    }
    var proc = #{@proc};
    if (proc !== nil) {
      return #{ `proc`.call self, key };
    }
    return #{@none};
  }
end

def []=(key, value)

def []=(key, value)
  %x{
    #{self}.map[key] = value;
    return value;
  }
end

def assoc(object)

def assoc(object)
  %x{
    var map = #{self}.map;
    for (var key in map) {
      if (#{`key` == object}) {
        return [key, map[key]];
      }
    }
    return nil;
  }
end

def clear

def clear
  %x{
    #{self}.map = {};
    return #{self};
  }
end

def clone

def clone
  %x{
    var result = __hash(),
        map    = #{self}.map,
        map2   = result.map;
    for (var key in map) {
      map2[key] = map[key];
    }
    return result;
  }
end

def default

def default
  @none
end

def default=(object)

def default=(object)
  @none = object
end

def default_proc

def default_proc
  @proc
end

def default_proc=(proc)

def default_proc=(proc)
  @proc = proc
end

def delete(key)

def delete(key)
  %x{
    var map = #{self}.map, result = map[key];
    if (result != null) {
      delete map[key];
      return result;
    }
    return nil;
  }
end

def delete_if(&block)

def delete_if(&block)
  %x{
    var map = #{self}.map, value;
    for (var key in map) {
      if ((value = block(key, map[key])) === __breaker) {
        return __breaker.$v;
      }
      if (value !== false && value !== nil) {
        delete map[key]
      }
    }
    return #{self};
  }
end

def each(&block)

def each(&block)
  %x{
    var map = #{self}.map;
    for (var key in map) {
      if (block(key, map[key]) === __breaker) {
        return __breaker.$v;
      }
    }
    return #{self};
  }
end

def each_key(&block)

def each_key(&block)
  %x{
    var map = #{self}.map;
    for (var key in map) {
      if (block(key) === __breaker) {
        return __breaker.$v;
      }
    }
    return #{self};
  }
end

def each_value(&block)

def each_value(&block)
  %x{
    var map = #{self}.map;
    for (var key in map) {
      if (block(map[key]) === __breaker) {
        return __breaker.$v;
      }
    }
    return #{self};
  }
end

def empty?

def empty?
  %x{
    for (var key in #{self}.map) {
      return false;
    }
    return true;
  }
end

def fetch(key, defaults = undefined, &block)

def fetch(key, defaults = undefined, &block)
  %x{
    var value = #{self}.map[key];
    if (value != null) {
      return value;
    }
    if (block !== nil) {
      var value;
      if ((value = block(key)) === __breaker) {
        return __breaker.$v;
      }
      return value;
    }
    if (defaults != null) {
      return defaults;
    }
    #{ raise "key not found" };
  }
end

def flatten(level=undefined)

def flatten(level=undefined)
  %x{
    var map = #{self}.map, result = [];
    for (var key in map) {
      var value = map[key];
      result.push(key);
      if (value._isArray) {
        if (level == null || level === 1) {
          result.push(value);
        }
        else {
          result = result.concat(#{`value`.flatten(`level - 1`)});
        }
      }
      else {
        result.push(value);
      }
    }
    return result;
  }
end

def has_key?(key)

def has_key?(key)
  `#{self}.map[key] != null`
end

def has_value?(value)

def has_value?(value)
  %x{
    var map = #{self}.map;
    for (var key in map) {
      if (#{`map[key]` == value}) {
        return true;
      }
    }
    return false;
  }
end

def hash

def hash
  `#{self}._id`
end

def index(object)

def index(object)
  %x{
    var map = #{self}.map;
    for (var key in map) {
      if (#{object == `map[key]`}) {
        return key;
      }
    }
    return nil;
  }
end

def indexes(*keys)

def indexes(*keys)
  %x{
    var result = [], map = #{self}.map, val;
    for (var i = 0, length = keys.length; i < length; i++) {
      val = map[keys[i]];
      if (val != null) {
        result.push(val);
      }
      else {
        result.push(#{@none});
      }
    }
    return result;
  }
end

def inspect

def inspect
  %x{
    var inspect = [], map = #{self}.map;
    for (var key in map) {
      inspect.push(#{`key`.inspect} + '=>' + #{`map[key]`.inspect});
    }
    return '{' + inspect.join(', ') + '}';
  }
end

def invert

def invert
  %x{
    var result = __hash(), map = #{self}.map, map2 = result.map;
    for (var key in map) {
      var obj = map[key];
      map2[obj] = key;
    }
    return result;
  }
end

def keep_if(&block)

def keep_if(&block)
  %x{
    var map = #{self}.map, value;
    for (var key in map) {
      var obj = map[key];
      if ((value = block(key, obj)) === __breaker) {
        return __breaker.$v;
      }
      if (value === false || value === nil) {
        delete map[key];
      }
    }
    return #{self};
  }
end

def keys

def keys
  %x{
    var result = [], map = #{self}.map;
    for (var key in map) {
      result.push(key);
    }
    return result;
  }
end

def length

def length
  %x{
    var length = 0, map = #{self}.map;
    for (var key in map) {
      length++;
    }
    return length;
  }
end

def merge(other, &block)

def merge(other, &block)
  %x{
    var map = #{self}.map, result = __hash(), map2 = result.map;
    for (var key in map) {
      map2[key] = map[key];
    }
    map = other.map;
    if (block === nil) {
      for (key in map) {
        map2[key] = map[key];
      }
    }
    else {
      for (key in map) {
        if (map2[key] == null) {
          map2[key] = map[key];
        }
        else {
          map2[key] = block(key, map2[key], map[key]);
        }
      }
    }
    return result;
  }
end

def merge!(other, &block)

def merge!(other, &block)
  %x{
    var map = #{self}.map, map2 = other.map;
    if (block === nil) {
      for (var key in map2) {
        map[key] = map2[key];
      }
    }
    else {
      for (key in map2) {
        if (map[key] == null) {
          map[key] = map2[key];
        }
        else {
          map[key] = block(key, map[key], map2[key]);
        }
      }
    }
    return #{self};
  }
end

def rassoc(object)

def rassoc(object)
  %x{
    var map = #{self}.map;
    for (var key in map) {
      var obj = map[key];
      if (#{`obj` == object}) {
        return [key, obj];
      }
    }
    return nil;
  }
end

def reject(&block)

def reject(&block)
  %x{
    var map = #{self}.map, result = __hash(), map2 = result.map;
    for (var key in map) {
      var obj = map[key], value;
      if ((value = block(key, obj)) === __breaker) {
        return __breaker.$v;
      }
      if (value === false || value === nil) {
        map2[key] = obj;
      }
    }
    return result;
  }
end

def replace(other)

def replace(other)
  %x{
    var map = #{self}.map = {}, map2 = other.map;
    for (var key in map2) {
      map[key] = map2[key];
    }
    return #{self};
  }
end

def select(&block)

def select(&block)
  %x{
    var map = #{self}.map, result = __hash(), map2 = result.map;
    for (var key in map) {
      var obj = map[key], value;
      if ((value = block(key, obj)) === __breaker) {
        return __breaker.$v;
      }
      if (value !== false && value !== nil) {
        map2[key] = obj;
      }
    }
    return result;
  }
end

def select!(&block)

def select!(&block)
  %x{
    var map = #{self}.map, value, result = nil;
    for (var key in map) {
      var obj = map[key];
      if ((value = block(key, obj)) === __breaker) {
        return __breaker.$v;
      }
      if (value === false || value === nil) {
        delete map[key];
        result = #{self}
      }
    }
    return result;
  }
end

def shift

def shift
  %x{
    var map = #{self}.map;
    for (var key in map) {
      var obj = map[key];
      delete map[key];
      return [key, obj];
    }
    return nil;
  }
end

def to_a

def to_a
  %x{
    var map = #{self}.map, result = [];
    for (var key in map) {
      result.push([key, map[key]]);
    }
    return result;
  }
end

def to_hash

def to_hash
  self
end

def to_json

def to_json
  %x{
    var inspect = [], map = #{self}.map;
    for (var key in map) {
      inspect.push(#{`key`.to_json} + ': ' + #{`map[key]`.to_json});
    }
    return '{' + inspect.join(', ') + '}';
  }
end

def to_native

def to_native
  %x{
    var result = {}, map = #{self}.map;
    for (var key in map) {
      var obj = map[key];
      if (obj.$to_native) {
        result[key] = #{`obj`.to_native};
      }
      else {
        result[key] = obj;
      }
    }
    return result;
  }
end

def value?(value)

def value?(value)
  %x{
    var map = #{self}.map;
    for (var assoc in map) {
      var v = map[assoc];
      if (#{`v` == value}) {
        return true;
      }
    }
    return false;
  }
end

def values

def values
  %x{
    var map    = #{self}.map,
        result = [];
    for (var key in map) {
      result.push(map[key]);
    }
    return result;
  }
end