dofile("../defs/entity_defs.lua")
dofile("../defs/aspect_defs.lua")

Entity = class("Entity")

local allow_overload = {
	init = true,
	set_position = true,
	set_item = true,
	set_team = true,
	set_location = true,
	inventory_changed = true,
	verify_hud_name = true,
	modify_health = true,
	next_col_row = true,
	setting_world = true,
	removing_world = true,
	aggressive_action_by = true,
	set_ai_target = true,
	init_stats = true,
	add_y_offset = true,
	stats_changed = true,
}
local skip_overload = {
	setup = true,
}
local required_methods = {
	init = true,
}

local no_op = function() end

function Entity:set_position(x,y,z)
	self.x = x
	self.y = y
	self.z = z
end

function Entity:setting_world(world)
end

function Entity:removing_world(world)	
end

local function generate_class(def, index)
	local class = class("Entity_"..index)
	class.def = def
	class.aspects = {}
	class._index = index
	class._aspect_setup = {}

	for method_name, method in pairs(Entity) do
		assert(not class[method_name])
		class[method_name] = method
	end

	for aspect, defalts in pairs(def.aspects) do
		local adef = ASPECT_DEFS[aspect]
		class.aspects[aspect] = defalts
		assert(adef, aspect)
		for method_name, method in pairs(adef) do
			if not skip_overload[method_name] then
				local old_method = class[method_name]
				if old_method then
					assert(allow_overload[method_name], "no nesting allowed".. method_name)
					class[method_name] = function(self, ...)
						old_method(self, ...)
						method(self, ...)
					end
				else
					class[method_name] = method
				end
			end
		end
		if adef.setup then
			class._aspect_setup[aspect] = adef.setup
		end
	end



	class.setup = function(self)
		for aspect, method in pairs(class._aspect_setup) do
			method(self, class.aspects[aspect])
		end
	end

	for method_name, method in pairs(required_methods) do
		if not class[method_name] then
			class[method_name] = no_op
		end
	end
	
	return class
end

local ENTITY_CLASSES = {}
entities = {}
function entities.init()
	for index, def in pairs(ENTITYS) do
		ENTITY_CLASSES[index] = generate_class(def, index)
	end
end

function Entity:setup_aspect(aspect)
	local defaults = self.aspects[aspect]
	local setup_method = self._aspect_setup[aspect]
	setup_method(self, defaults)
end

function Entity:new(actor_type, x, y, z)
	local def = assert(ENTITYS[actor_type], actor_type)
	local class_table = ENTITY_CLASSES[actor_type]
	local a = instance(class_table)	
	a.x = x or 0
	a.y = y or 0
	a.z = z or 0
	a:setup()
	a:init()
	return a
end


