function OnMsg.CityStart() RDM_Controller:GameInit('new') end
function OnMsg.LoadGame() RDM_Controller:GameInit('load') end

-- @GlobalFunctions
-- =====================================================================================
function RDM_LockUnlock(mod_classname, tech_id) RDM_Controller:LockUnlock(mod_classname, tech_id) end

function RDM_AddBuildingRules(rules) 	RDM_Controller:AddBuildingRules(rules) end
function RDM_AddUpgradeRules(rules) 	RDM_Controller:AddUpgradeRules(rules) end
function RDM_AddModifiersRules(rules) 	RDM_Controller:AddModifiersRules(rules) end
function RDM_AddCropRules(rules) 		RDM_Controller:AddCropRules(rules) end

-- var mod_classname string from ModRegister
function RDM_CheckModLoaded(mod_classname) return RDM_Controller:CheckModLoaded(mod_classname) end
function RDM_CheckModLoadedById(mod_id) return ModsLoaded and table.find(ModsLoaded, "id", mod_id) end

function RDM_IsNewGame(moment) if moment == 'new' then return true end end
function RDM_IsLoadGame(moment) if moment == 'load' then return true end end

-- @Class RDM_Controller
-- =====================================================================================
DefineClass.RDM_Controller = {
	ModRegister = false,
	rules_building = {},
	rules_upgrade = {},
	rules_modifiers = {},
	rules_crops = {},
}

function RDM_Controller:Init() 
	self.ModRegister = RDM_ModRegister or empty_table
	Msg("RDM_ControllerLoaded", self) 
end

function RDM_Controller:GameInit(moment)
	-- Utile pour Locked/Unlocked certains objets/modifiers dans une partie existante quand le mod est chargé pour la première fois
	self:LockBuildings()
	Msg("RDM_GatherLockBuildings")
	
	self:LockCrops()
	Msg("RDM_GatherLockCrops")
	
	self:UnlockUpgrades()
	Msg("RDM_GatherUnlockUpgrades") -- To unlock Upgrades without conditions
	
	-- Msg("RDM_AfterControllerGameInit", self, moment)  -- [DEPRECIATED]
	Msg("RDM_FixerThrowFixes", RDM_Fixer, moment)
end

function RDM_Controller:CountMod() 
	local count = 0
	for key, value in pairs(RDM_ModRegister) do
		count = count + 1
	end
	return count
end

function RDM_Controller:CheckModLoaded(mod_classname)
	return self.ModRegister[mod_classname] and true or false
end

function RDM_Controller:GetModName(mod_classname)
	return self.ModRegister[mod_classname].ModTitle and true or false
end

function RDM_Controller:GetMod(classname) return self.ModRegister[classname] end

-- @OnMsg.TechResearched : Lock/Unlock building/upgrades/modifiers lorsqu'une recherche est terminée.
function RDM_Controller:LockUnlock(mod_classname, tech_id)
	local mod = self:GetMod(mod_classname)

	if mod then
		if #mod.rules_buildings > 0 then
			for _, rule in ipairs(mod.rules_buildings) do
				local tech, bld_id = rule[2], rule[1]
				if tech_id == tech then
					UnlockBuilding(bld_id)
				end
			end
		end
		
		if #mod.rules_upgrades > 0 then
			for _, rule in ipairs(mod.rules_upgrades) do
				local tech, upgrade_id = rule[2], rule[1]
				if tech_id == tech then
					UnlockUpgrade(upgrade_id)
				end
			end
		end
		
		-- modifiers = { {id, label, prop[], tech }, {...} }
		if #mod.rules_modifiers > 0 then
			for _, rule in ipairs(mod.rules_modifiers) do
				local tech, modifier_id, modifier_label, modifier_props = rule[4], rule[1], rule[2], rule[3]
				if tech_id == tech then
					CreateLabelModifier(modifier_id, modifier_label, modifier_props[1], modifier_props[2], modifier_props[3])
				end
			end
		end
		
		-- crops
		if #mod.rules_crops > 0 then
			for _, rule in ipairs(mod.rules_crops) do
				local tech, crop_id = rule[2], rule[1]
				if tech_id == tech then
					UnlockCrop(crop_id, tech)
				end
			end
		end
		
	else
		ModLog("[SILVA][Error] Mod classname: ".. mod_classname .. " doesn't exist.")
	end
end

-- @LockBuildings
function RDM_Controller:LockBuildings(rules)
	local rules = rules or self.rules_building
	if #rules > 0 then
		for _, rule in ipairs(rules) do
			local tech_id, bld_id = rule[2], rule[1]
			if IsTechResearched(tech_id) ~= 1 then
				-- Disable building
				local tech_name = TechDef[tech_id].display_name
				LockBuilding(bld_id, "disable", T{3956, "Research <em><tech_name></em> to unlock this building.", tech_name = tech_name})
			end
		end
	end
end

function RDM_Controller:AddBuildingRules(rules)
	for _, rule in ipairs(rules) do
		table.insert(self.rules_building, rule)
	end
end

-- @UnlockUpgrades
function RDM_Controller:UnlockUpgrades(rules)
	local rules = rules or self.rules_upgrade
	if #rules > 0 then
		for _, rule in ipairs(rules) do
			local tech_id, upgrade_id = rule[2], rule[1]
			if IsTechResearched(tech_id) == 1 then
				-- Unlock upgrade
				UnlockUpgrade(upgrade_id)
			end
		end
	end
end

function RDM_Controller:AddUpgradeRules(rules)
	for _, rule in ipairs(rules) do
		table.insert(self.rules_upgrade, rule)
	end
end

-- @ApplyModifier
function RDM_Controller:ApplyModifiers(rules)
	local rules = rules or self.rules_modifiers
	for _, rule in ipairs(rules) do
		local tech_id, modifier_id, modifier_label, modifier_props = rule[4], rule[1], rule[2], rule[3]
		if IsTechResearched(tech_id) == 1 then
			CreateLabelModifier(modifier_id, modifier_label, modifier_props[1], modifier_props[2], modifier_props[3])
		end
	end
end

function RDM_Controller:AddModifiersRules(rules)
	for _, rule in ipairs(rules) do
		table.insert(self.rules_modifiers, rule)
	end
end

-- @UnlockCrops
function RDM_Controller:UnlockCrops(rules)
	local rules = rules or self.rules_crop
	if #rules > 0 then
		for _, rule in ipairs(rules) do
			local tech_id, crop_id = rule[2], rule[1]
			if IsTechResearched(tech_id) == 1 and not IsCropAvailable(crop_id) then
				UnlockCrop(crop_id, tech_id)
			end
		end
	end
end

-- @LockCrops
function RDM_Controller:LockCrops(rules)
	local rules = rules or self.rules_crops
	if #rules > 0 then
		for _, rule in ipairs(rules) do
			local tech_id, crop_id = rule[2], rule[1]
			if IsTechResearched(tech_id) ~= 1 then
				LockCrop(crop_id, tech_id)
			end
		end
	end
end

function RDM_Controller:AddCropRules(rules)
	for _, rule in ipairs(rules) do
		table.insert(self.rules_crops, rule)
	end
end