local Vector3 = require "types.vector3"

local util = {}

function util.printt(t)
  if type(t) == 'table' then
      local s = '{ '
      for k,v in pairs(t) do
        if type(k) ~= 'number' then k = '"'..k..'"' end
        s = s .. '['..k..'] = ' .. util.printt(v) .. ','
      end
      return s .. '} '
  else
      return tostring(t)
  end
end

function util.b2n(value)
  return value and 1 or 0
end

---creates a list of vertices for a draw_quad call from a plane defined by position and normal
---@param position Vector3
---@param normal Vector3
---@param size number
---@return table
function util.create_plane_quad(position, normal, size)
  local axis = Vector3.UP:cross(normal)
  local angle = math.acos(Vector3.UP:dot(normal))

  local vlist = {
    v0 = (Vector3(-0.5, 0, 0.5) * size):rotated(axis, angle) + position,
    v1 = (Vector3(0.5, 0, 0.5) * size):rotated(axis, angle) + position,
    v2 = (Vector3(0.5, 0, -0.5) * size):rotated(axis, angle) + position,
    v3 = (Vector3(-0.5, 0, -0.5) * size):rotated(axis, angle) + position,
  }

  return vlist
end

---creates a shallow copy of the table t
---@param t table
---@return table
function util.shallow_copy(t)
  local t2 = {}
  for k, v in pairs(t) do
    t2[k] = v
  end
  return t2
end

---returns the intersection of tables t1 and t2, optionally overwriting t1's keys with t2's
---@param t1 table
---@param t2 table
---@param overwrite boolean?
---@return table
function util.merge(t1, t2, overwrite)
  local t3 = util.shallow_copy(t1)
  overwrite = overwrite or true
  for k, v in pairs(t2) do
    if overwrite or not t3[k] then
      t3[k] = v
    end
  end
  return t3
end

---Finds the index of value in list t. If the value does not exist in the list, returns -1.
---@param t table
---@param value any
---@return integer
function util.list_find(t, value)
  local idx = -1
  for i, v in ipairs(t) do
    if v == value then
      idx = i
      break
    end
  end
  return idx
end

---Removes an element from a list, if it exists. Does nothing if the value doesn't exist.
---@param t table
---@param value any
function util.list_remove_value(t, value)
  local idx = util.list_find(t, value)
  if idx ~= -1 then
    table.remove(t, idx)
  end
end

---Inserts value into the list only if it does not exist.
---@param t table
---@param value any
function util.list_insert_once(t, value)
  if util.list_find(t, value) ~= -1 then return end
  table.insert(t, value)
end

---linear interpolation
---@param a number
---@param b number
---@param t number in [0, 1]
---@return number
function util.lerp(a, b, t)
  return a + t * (b - a)
end

---constrains v between min and max
---@param v number
---@param min number
---@param max number
---@return number
function util.clamp(v, min, max)
  return math.max(math.min(v, max), min)
end


return util