local SceneManager = {
	currentSceneName = "",
	targetSceneName = ""
}

local ASYNC_FINISH_PROGRESS = 0.899

local EMPTY_SCENE_PATH = "assets/scenes/empty_scene.unity"

SceneManager.SCENE_NAME = {
	MAIN_CITY = "app/scene/maincity/maincity_scene",
	BATTLE = "app/scene/battle/battle_scene",
}

-- sceneName:目标场景路径，这里是lua的路径，不是资源的路径
-- showLoading:显示指定的加载界面
-- callback:切换完成后的回调
-- immediately:是否立即切换，是的话会直接切换到目标场景,否则的话会创建一个空场景并先切换到空场景，然后垃圾回收，然后再切换到目标场景
-- keepUI:是否关闭所有UI界面
-- preloadList:下一个场景加载完后需要预加载的资源列表
-- closeLoadingCallback:关闭过场动画时的callback

function SceneManager:_changeScene(params)
	local sceneName = params.sceneName or ""
	if sceneName == "" then
		return false
	end
	-- 正在切换场景中
	if self.targetSceneName ~= "" then
		return false
	end
	-- 当前场景就是目标场景
	if self.currentSceneName == sceneName then
		if not params.reloadScene then
			return false
		end
		params.immediately = false
	end
	self.params = params
	self.targetSceneName = sceneName
	return true
end

function SceneManager:changeScene(params)
	if not self:_changeScene(params) then
		return false
	end
	UIManager:disableTouch()
	UIManager:showLoading(self.params.showLoading, function()
		self:loadScene()
	end)
	return true
end

function SceneManager:loadScene()
	if not self.params.keepUI then
		UIManager:closeAllUI()
	end
	UIManager:hideToastAndMessageBox()
	self.targetScene = require(self.targetSceneName):create(self.params.sceneParams)
	if self.params.immediately then
		self:loadSceneABAsync()
	else
		self:createEmptyScene(function()
			self:loadSceneABAsync()
		end)
	end
end

function SceneManager:createEmptyScene(nextStep)
	local function loadEmptyScene()
		local realPath = ResourceManager:getSceneLoadPath(EMPTY_SCENE_PATH)
		local asyncOperation = CS.UnityEngine.SceneManagement.SceneManager.LoadSceneAsync(realPath, CS.LoadSceneMode.Additive)
		asyncOperation.allowSceneActivation = false
		self:scheduleGlobal(function()
			if asyncOperation.progress >= ASYNC_FINISH_PROGRESS then
				if not asyncOperation.allowSceneActivation then
					if self.currentScene then
						self.currentScene:_onClose()
					end
					asyncOperation.allowSceneActivation = true
				end
			end
			if asyncOperation.isDone then
				nextStep()
				return true
			end
		end, 0.01)
	end
	if USE_AB then
		ResourceManager:loadSceneAsync(EMPTY_SCENE_PATH, function()
			loadEmptyScene()
		end)
	else
		loadEmptyScene()
	end
end

function SceneManager:loadSceneABAsync()
	if USE_AB then
		local resPath = self.targetScene:getResPath()
		ResourceManager:loadSceneAsync(resPath, function()
			self:LoadSceneAsync()
		end)
	else
		self:LoadSceneAsync()
	end
end

function SceneManager:LoadSceneAsync()
	local resPath = self.targetScene:getResPath()
	local realPath = ResourceManager:getSceneLoadPath(resPath)
	local asyncOperation = CS.UnityEngine.SceneManagement.SceneManager.LoadSceneAsync(realPath, CS.LoadSceneMode.Additive)
	asyncOperation.allowSceneActivation = false
	self:scheduleGlobal(function()
		if asyncOperation.progress >= ASYNC_FINISH_PROGRESS then
			if not asyncOperation.allowSceneActivation then
				if self.params.immediately and self.currentScene then
					self.currentScene:_onClose()
				end
				asyncOperation.allowSceneActivation = true
			end
		end
		if asyncOperation.isDone then
			self:onLoadSceneFinished()
			return true
		end
	end, 0.01)
end

function SceneManager:onLoadSceneFinished()
	local function nextStep()
		if self.currentScene then
			local resPath = self.currentScene:getResPath()
			ResourceManager:unloadScene(resPath)
		end
		if not self.params.immediately then
			ResourceManager:unloadScene(EMPTY_SCENE_PATH)
		end
		if self.params.preloadList then
			local preloadCount = #self.params.preloadList
			local loadedCount = 0
			local function loadCheck( asset )
				loadedCount = loadedCount + 1
				local ratio = loadedCount / preloadCount
				if loadedCount >= preloadCount then
					self:onFinished()
				end
			end
			if preloadCount > 0 then
				for i, resPath in ipairs(self.params.preloadList) do
					ResourceManager:asyncLoad(resPath, loadCheck)
				end
			else
				self:onFinished()
			end
		else
			self:onFinished()
		end
	end
	self:garbageCollect(nextStep)
end

function SceneManager:onFinished()
	LocalData:save()
	self.targetScene:_init(self.params.init)
	if self.targetScene:closeLoadingAuto() then
		UIManager:closeLoading(self.params.closeLoadingCallback)
		UIManager:enableTouch()
	else
		if self.params.closeLoadingCallback then
			self.targetScene:addCloseLoadingCallback(self.params.closeLoadingCallback)
		end
	end
	self.currentSceneName = self.targetSceneName
	self.currentScene = self.targetScene
	self.targetSceneName = ""
	self.targetScene = nil
	local finishCallback = self.params.callback
	self.params = nil
	if finishCallback then
		finishCallback(self.currentScene)
	end
end

function SceneManager:getCurrentScene()
	return self.currentScene
end

function SceneManager:getCurrentSceneName()
	return self.currentSceneName
end

function SceneManager:getIsInMainCityScene()
	return self.currentSceneName == SceneManager.SCENE_NAME.MAIN_CITY
end

function SceneManager:garbageCollect(callback)
	ResourceManager:unloadAllDelayAssets()
	CS.BF.BFMain.Instance.LuaMgr:LuaEnvFullGC(30000)
	collectgarbage("collect")
	local asyncOperation = CS.UnityEngine.Resources.UnloadUnusedAssets()
	local function onUnloadComplete(opration)
		asyncOperation:completed("-", onUnloadComplete)
		if callback then
			callback()
		end
	end

	asyncOperation:completed("+", onUnloadComplete)
end

function SceneManager:scheduleGlobal(func, inter)
	SchedulerManager:scheduleGlobal(func, inter)
end

function SceneManager:clear()
end

-- 只有一个场景
function SceneManager:enterMainScene()
	local scene = "app/scene/main/main_scene"
	self.mainScene = require(scene):create()
	self.mainScene:init()

	self.currentScene = self.mainScene
end

return SceneManager