---@meta

---@class util
util = {
  table = {}
}

---Deep copies a table
---@generic T
---@param object T
---@return T
function table.deepcopy(object) end

---Compares a table for shallow equality
---@param tbl1 any
---@param tbl2 any
---@return boolean
function table.compare(tbl1, tbl2) end

util.table.deepcopy = table.deepcopy
util.table.compare = table.compare
util.copy = util.table.deepcopy

---The distance between two MapPositions
---@param position1 MapPosition
---@param position2 MapPosition
---@return double
function util.distance(position1, position2) end

---@param pos MapPosition
---@return string
function util.positiontostr(pos) end

---@param ticks uint
---@return string
function util.formattime(ticks) end

--- supports 'rrggbb', 'rgb', 'rrggbbaa', 'rgba', 'ww', 'w'
---@param hex string
---@return Color
function util.color(hex) end

---Multiplies all color channels by alpha
---@generic T: Color
---@param color T
---@return T
function util.premul_color(color) end

---Mixes two colors together
---@param c1 Color
---@param c2 Color
---@return Color
function util.mix_color(c1, c2) end

---@param c1 Color
---@param n number
---@return Color
function util.multiply_color(c1, n) end

---@param color Color
---@param alpha number
---@param normalized_alpha boolean?
---@return Color
function util.get_color_with_alpha(color, alpha, normalized_alpha) end

---@type {[defines.direction]:Vector}
util.direction_vectors = {
  [defines.direction.north]          = { 0, -1 },
  [defines.direction.northnortheast] = { 1, -2 },
  [defines.direction.northeast]      = { 1, -1 },
  [defines.direction.eastnortheast]  = { 2, -1 },
  [defines.direction.east]           = { 1,  0 },
  [defines.direction.eastsoutheast]  = { 2,  1 },
  [defines.direction.southeast]      = { 1,  1 },
  [defines.direction.southsoutheast] = { 1,  2 },
  [defines.direction.south]          = { 0,  1 },
  [defines.direction.southsouthwest] = {-1,  2 },
  [defines.direction.southwest]      = {-1,  1 },
  [defines.direction.westsouthwest]  = {-2,  1 },
  [defines.direction.west]           = {-1,  0 },
  [defines.direction.westnorthwest]  = {-2, -1 },
  [defines.direction.northwest]      = {-1, -1 },
  [defines.direction.northnorthwest] = {-1, -2 },
}

---@param position Vector
---@param direction defines.direction
---@param distance number
---@return Vector
function util.moveposition(position, direction, distance) end


---@param position Vector
---@param orientation number
---@return Vector
function util.rotate_position(position, orientation) end

---@param direction defines.direction
---@return defines.direction
function util.oppositedirection(direction) end

---@param count integer
---@param stripes table
---@return table
function util.multiplystripes(count, stripes) end

---@param x number
---@param y number
---@return Vector
function util.by_pixel(x, y) end

---@param x number
---@param y number
---@return Vector
function util.by_pixel_hr(x, y) end

---@generic T: table
---@param table_ T
---@param fun_ fun(t: T)
---@return T
function util.foreach_sprite_definition(table_, fun_) end

---@param a Vector
---@param b Vector
---@return Vector
function util.add_shift(a, b) end

---@generic T: table
---@param offset_ Vector
---@param table_ T
---@return T
function util.add_shift_offset(offset_, table_) end

---@generic T: Vector
---@param shift T
---@param scale number
---@return T|Vector
function util.mul_shift(shift, scale) end

---@param amount number
---@param append_suffix boolean?
---@return string
function util.format_number(amount, append_suffix) end

---@generic K: AnyBasic
---@param t {[K]:number}
---@param k K
---@param v? number
function util.increment(t, k, v) end

---If both value and data are truthy, returns data, otherwise returns false
---@generic D: any
---@param value any
---@param data D
---@return D|false
function util.conditional_return(value, data) end

-- Recursively merges and/or deep-copies tables.
-- Entries in later tables override entries in earlier ones, unless
-- both entries are themselves tables, in which case they are recursively merged.
-- Non-merged tables are deep-copied, so that the result is brand new.
---@param tables table[]
---@return table
function util.merge(tables) end

---@param entity LuaControl?
---@param item_dict ItemStackDefinition?
util.insert_safe = function(entity, item_dict) end

---@param entity LuaControl?
---@param item_dict ItemStackDefinition?
util.remove_safe = function(entity, item_dict) end

---@param string string
---@return string[]
util.split_whitespace = function(string) end

---@param inputstr string
---@param sep string
---@return string[]
util.split = function(inputstr, sep) end

---@param str string
---@param start string
---@return boolean
util.string_starts_with = function(str, start) end

---@param str string
---@param what string
---@param with string
util.string_replace = function(str, what, with) end

---@generic X: number, Lower: number, Upper: number
---@param x X
---@param lower Lower
---@param upper Upper
---@return X|Lower|Upper
util.clamp = function(x, lower, upper) end

---@return string
util.get_walkable_tile = function() end

-- This function takes 2 icons tables, and adds the second to the first, but applies scale,
-- shift and tint to the entire second set.\
-- This allows you to manipulate the entire second icons table in the same way as you would
-- manipulate a single icon when adding to the icons table.
---@param icons1 data.IconData[]
---@param icons2 data.IconData[]
---@param inputs {["scale"]:number?, ["shift"]:Vector?, ["tint"]:Color?}
---@param default_icon_size integer
---@return data.IconData[]
function util.combine_icons(icons1, icons2, inputs, default_icon_size) end

---@param technology_icon string
---@return data.IconData[]
function util.technology_icon_constant_damage(technology_icon) end

---@param technology_icon string
---@return data.IconData[]
function util.technology_icon_constant_speed(technology_icon) end

---@param technology_icon string
---@return data.IconData[]
function util.technology_icon_constant_movement_speed(technology_icon) end

---@param technology_icon string
---@return data.IconData[]
function util.technology_icon_constant_range(technology_icon) end

---@param technology_icon string
---@return data.IconData[]
function util.technology_icon_constant_planet(technology_icon) end

---@param technology_icon string
---@return data.IconData[]
function util.technology_icon_constant_equipment(technology_icon) end

---@param technology_icon string
---@return data.IconData[]
function util.technology_icon_constant_followers(technology_icon) end

---@param technology_icon string
---@return data.IconData[]
function util.technology_icon_constant_capacity(technology_icon) end

---@param technology_icon string
---@return data.IconData[]
function util.technology_icon_constant_stack_size(technology_icon) end

---@param technology_icon string
---@return data.IconData[]
function util.technology_icon_constant_productivity(technology_icon) end

---@param technology_icon string
---@return data.IconData[]
function util.technology_icon_constant_recipe_productivity(technology_icon) end

---@param technology_icon string
---@return data.IconData[]
function util.technology_icon_constant_braking_force(technology_icon) end

---@param technology_icon string
---@return data.IconData[]
function util.technology_icon_constant_mining(technology_icon) end

---@param energy string
---@return number
function util.parse_energy(energy) end

---@param product data.ProductPrototype
---@return number
function util.product_amount(product) end

---@return table
function util.empty_sprite() end

---@param animation_length number
---@return table
function util.empty_animation(animation_length) end

---@return table
function util.empty_icon() end

---@generic L: table
---@param layer L
---@return L
function util.draw_as_glow(layer) end

---@generic T : table
---@param path string
---@param table T
---@return T
function util.sprite_load(path, table) end

---@param spritesheets table[]
---@return table[]
function util.spritesheets_to_pictures(spritesheets) end

-- Does not handle:
--  - explicit tile filters in "selection-tool" items
--  - ItemPrototype::place_as_tile
--  - TilePrototype::next_direction
--  - TilePrototype::transition_merges_with_tile
--  - general tile transitions, only removes tile names from water_tile_type_names
---@param data table --Seriously pass the global data
---@param array_of_tiles_to_remove string[]
function util.remove_tile_references(data, array_of_tiles_to_remove) end

---Remove the first occurance of value from the array
---@param list any[]
---@param value any
util.remove_from_list = function(list, value) end

---@param list any[]
---@return {[any]: true}
util.list_to_map = function(list) end

---@param raw_product data.ProductPrototype
---@return data.ProductPrototype
util.normalize_recipe_product = function(raw_product) end

---@param recipe data.RecipePrototype
---@return data.ProductPrototype[]
util.normalize_recipe_products = function(recipe) end

---Returns the normalized main product or nil if the recipe defintion is invalid or there is no main product
---@param recipe data.RecipePrototype
---@param normalized_products data.ProductPrototype[]
---@return data.ProductPrototype
util.get_recipe_main_product = function(recipe, normalized_products) end

gram = 1
grams = gram
kg = 1000*grams
tons = 1000*kg
second = 60
minute = 60 * second
hour = 60 * minute
meter = 1
kilometer = 1000

return util
