var collision2d = {}

collision2d.body = function(config) {
  var c = config || {}
  return {
    type: c.type || 'aabb',
    width: c.width || 0,
    height: c.height || 0,
    radius: c.radius || 0,
    offset: c.offset || {x: 0, y: 0},
    layer: c.layer || 0,
    mask: c.mask || 0xFFFF
  }
}

function body_center(body, pos) {
  return {
    x: pos.x + body.offset.x,
    y: pos.y + body.offset.y
  }
}

function test_aabb_aabb(a, ap, b, bp) {
  var ac = body_center(a, ap)
  var bc = body_center(b, bp)
  var ahw = a.width * 0.5
  var ahh = a.height * 0.5
  var bhw = b.width * 0.5
  var bhh = b.height * 0.5
  return abs(ac.x - bc.x) < ahw + bhw && abs(ac.y - bc.y) < ahh + bhh
}

function test_circle_circle(a, ap, b, bp) {
  var ac = body_center(a, ap)
  var bc = body_center(b, bp)
  var dx = ac.x - bc.x
  var dy = ac.y - bc.y
  var r = a.radius + b.radius
  return dx * dx + dy * dy < r * r
}

function test_aabb_circle(aabb, ap, circ, cp) {
  var ac = body_center(aabb, ap)
  var cc = body_center(circ, cp)
  var hw = aabb.width * 0.5
  var hh = aabb.height * 0.5
  var cx = max(ac.x - hw, min(cc.x, ac.x + hw))
  var cy = max(ac.y - hh, min(cc.y, ac.y + hh))
  var dx = cc.x - cx
  var dy = cc.y - cy
  return dx * dx + dy * dy < circ.radius * circ.radius
}

collision2d.test = function(a, a_pos, b, b_pos) {
  if (a.layer & b.mask == 0 || b.layer & a.mask == 0)
    return false

  if (a.type == 'aabb' && b.type == 'aabb')
    return test_aabb_aabb(a, a_pos, b, b_pos)
  if (a.type == 'circle' && b.type == 'circle')
    return test_circle_circle(a, a_pos, b, b_pos)
  if (a.type == 'aabb' && b.type == 'circle')
    return test_aabb_circle(a, a_pos, b, b_pos)
  if (a.type == 'circle' && b.type == 'aabb')
    return test_aabb_circle(b, b_pos, a, a_pos)
  return false
}

collision2d.overlap = function(body, pos, others) {
  var results = []
  var i = 0
  var other = null
  for (i = 0; i < length(others); i++) {
    other = others[i]
    if (collision2d.test(body, pos, other.body, other.pos))
      push(results, other)
  }
  return results
}

collision2d.overlap_point = function(point, bodies) {
  var results = []
  var i = 0
  var b = null
  var c = null
  var hw = 0
  var hh = 0
  var dx = 0
  var dy = 0
  for (i = 0; i < length(bodies); i++) {
    b = bodies[i]
    c = body_center(b.body, b.pos)
    if (b.body.type == 'aabb') {
      hw = b.body.width * 0.5
      hh = b.body.height * 0.5
      if (abs(point.x - c.x) < hw && abs(point.y - c.y) < hh)
        push(results, b)
    } else if (b.body.type == 'circle') {
      dx = point.x - c.x
      dy = point.y - c.y
      if (dx * dx + dy * dy < b.body.radius * b.body.radius)
        push(results, b)
    }
  }
  return results
}

return collision2d
