local BaseObject = require "app/bf/unity/base_object"
local EffectObject = require "app/bf/unity/effect_object"
local CharacterObject = require "app/bf/unity/character_object"
local UISpineObject = require "app/bf/unity/ui_spine_object"
local MeshSpineObject = require "app/bf/unity/mesh_spine_object"
local UIPrefabObject = class("UIPrefabObject", BaseObject)

local BF_PREFAB_HELPER = GConst.TYPEOF_UNITY_CLASS.BF_PREFAB_HELPER
local BF_UI_TOUCH_EVENT = GConst.TYPEOF_UNITY_CLASS.BF_UI_TOUCH_EVENT
local BF_UI_DRAG_EVENT = GConst.TYPEOF_UNITY_CLASS.BF_UI_DRAG_EVENT
local BF_UI_CELL_DRAG_EVNET = GConst.TYPEOF_UNITY_CLASS.BF_UI_CELL_DRAG_EVENT
local UI_MASKABLE_GRAPHIC = GConst.TYPEOF_UNITY_CLASS.UI_MASKABLE_GRAPHIC

local LANGUAGE_ATLAS_PATH = "assets/arts/language/%s/sprites/%s/%s.asset"
local LANGUAGE_SPRITE_PATH = "assets/arts/language/%s/sprites/%s/%s.png"
local DELAULT_LONG_PRESS_TIME = 0.5

local Vector2 = BF.Vector2(0, 0)

local Color4 = BF.Color(0, 0, 0, 0)

local hash = GFunc.hash

local CHILDMAP_METATABLE = {
	__index = function(t, k)
		if rawget(t, k) == nil then
			local v = rawget(t, hash(k))
			if v then
				rawset(t, k, v)
			end
			return v
		end
		return rawget(t, k)
	end
}

local function _createDefaultChildObject(self, index, gameObject)
	local child = UIPrefabObject:create()
	child:initWithPrefabHelper(self.prefabHelper, index, gameObject)
	return child
end

local function _createUIChildObject(self, index, gameObject)
	local child = UIPrefabObject:create()
	child:initWithPrefab(nil, gameObject)
	child:initPrefabHelper()
	return child
end

local function _createEffectChildObject(self, index, gameObject)
	local child = EffectObject:create()
	child:initWithPrefab(nil, gameObject)
	return child
end

local function _createSpineUIChildObject(self, index, gameObject)
	local child = UISpineObject:create()
	child:initWithPrefab(nil, gameObject)
	child:getAnimationState()
	local skeletonGraphic = child:getSkeletonGraphic()
	skeletonGraphic:Initialize(false)
	skeletonGraphic.raycastTarget = false
	return child
end

local function _createSpineMeshChildObject(self, index, gameObject)
	local child = MeshSpineObject:create()
	child:initWithPrefab(nil, gameObject)
	child:getAnimationState()
	local skeletonAnimation = child:getSkeletonAnimation()
	skeletonAnimation:Initialize(false)
	return child
end

local function _createCharacterChildObject(self, index, gameObject)
	local child = CharacterObject:create()
	child:initWithPrefab(nil, gameObject)
	return child
end

UIPrefabObject.createChildObject = {
	[GConst.GAME_OBJECT_TYPE.DEFAULT] = _createDefaultChildObject,
	[GConst.GAME_OBJECT_TYPE.UI_OBJECT] = _createUIChildObject,
	[GConst.GAME_OBJECT_TYPE.EFFECT_OBJECT] = _createEffectChildObject,
	[GConst.GAME_OBJECT_TYPE.MODEL_OBJECT] = _createDefaultChildObject,
	[GConst.GAME_OBJECT_TYPE.CHARACTER_OBJECT] = _createCharacterChildObject,
	[GConst.GAME_OBJECT_TYPE.TIMELINE_OBJECT] = _createDefaultChildObject,
	[GConst.GAME_OBJECT_TYPE.SPINE_UI_OBJECT] = _createSpineUIChildObject,
	[GConst.GAME_OBJECT_TYPE.SPINE_MESH_OBJECT] = _createSpineMeshChildObject,
}

function UIPrefabObject:initWithPrefabHelper(prefabHelper, index, gameObject)
	if self.prefabHelper == nil then
		self.prefabHelper = prefabHelper
		self.objectIndex = index
		self.gameObject = gameObject
	end
end

function UIPrefabObject:initPrefabHelper()
	if self.gameObject == nil then
		return
	end
	self.prefabHelper = self.gameObject:GetComponent(BF_PREFAB_HELPER)
	if self.prefabHelper then
		self.objectIndex = self.prefabHelper:GetRootPrefabIndex()
	end
end

function UIPrefabObject:getPrefabHelper()
	return self.prefabHelper
end

function UIPrefabObject:genAllChildren(isRegenerate)
	local childMap
	if self.isGenChildren then
		if isRegenerate then
			childMap = {}
			for k, child in ipairs(self.childList) do
				local name = child:getName()
				if name ~= "" and childMap[name] == nil then
					childMap[name] = child
				end
			end
		else
			return self.childMap
		end
	else
		self.isGenChildren = true
		childMap = {}
		if self.prefabHelper then
			local childNum = self.prefabHelper:GetListCount()
			for i = 0, childNum do
				if i ~= self.objectIndex then
					local gameObject = self.prefabHelper:GetGameObjectByIndex(i)
					local objectType = self.prefabHelper:GetObjectTypeByIndex(i)
					local hashName = self.prefabHelper:GetHashNameByIndex(i)
					local func = self.createChildObject[objectType] or _createDefaultChildObject
					local child = func(self, i, gameObject)
					child:setName(hashName)
					child:setAdmin(self)
					if childMap[hashName] == nil then
						childMap[hashName] = child
					end
					table.insert(self.childList, child)
				end
			end
		end
	end
	setmetatable(childMap, CHILDMAP_METATABLE)
	self.childMap = childMap
	return childMap
end

function UIPrefabObject:getChildrenMap()
	return self.childMap
end

function UIPrefabObject:getGameObject()
	if self.gameObject == nil and self.objectIndex then
		self.gameObject = self.prefabHelper:GetGameObjectByIndex(self.objectIndex)
	end
	return self.gameObject
end

function UIPrefabObject:setAnchoredPositionX(x)
	if self.prefabHelper then
		self.prefabHelper:SetAnchoredPositionX(self.objectIndex, x)
	else
		BaseObject.setAnchoredPositionX(self, x)
	end
end

function UIPrefabObject:setAnchoredPositionY(y)
	if self.prefabHelper then
		self.prefabHelper:SetAnchoredPositionY(self.objectIndex, y)
	else
		BaseObject.setAnchoredPositionY(self, y)
	end
end

function UIPrefabObject:setAnchoredPosition(x, y)
	if self.prefabHelper then
		self.prefabHelper:SetAnchoredPosition(self.objectIndex, x, y)
	else
		BaseObject.setAnchoredPosition(self, x, y)
	end
end

function UIPrefabObject:fastGetAnchoredPosition()
	if self.prefabHelper then
		self.prefabHelper:CacheAnchoredPosition(self.objectIndex)
		return self.prefabHelper.PositionX, self.prefabHelper.PositionY
	else
		local anchoredPosition = self:getTransform().anchoredPosition
		return anchoredPosition.x, anchoredPosition.y
	end
end

function UIPrefabObject:fastGetAnchoredPositionX()
	if self.prefabHelper then
		self.prefabHelper:CacheAnchoredPosition(self.objectIndex)
		return self.prefabHelper.PositionX
	else
		local anchoredPosition = self:getTransform().anchoredPosition
		return anchoredPosition.x
	end
end

function UIPrefabObject:fastGetAnchoredPositionY()
	if self.prefabHelper then
		self.prefabHelper:CacheAnchoredPosition(self.objectIndex)
		return self.prefabHelper.PositionY
	else
		local anchoredPosition = self:getTransform().anchoredPosition
		return anchoredPosition.y
	end
end

function UIPrefabObject:getAnchoredPosition()
	if self.prefabHelper then
		return self.prefabHelper:GetAnchoredPosition(self.objectIndex)
	else
		return BaseObject.getAnchoredPosition(self)
	end
end

function UIPrefabObject:addAnchoredPosition(x, y)
	if self.prefabHelper then
		self.prefabHelper:AddAnchoredPosition(self.objectIndex, x, y)
	else
		BaseObject.addAnchoredPosition(self, x, y)
	end
end

function UIPrefabObject:setAnchorMin(x, y)
	if self.prefabHelper then
		self.prefabHelper:SetAnchorMin(self.objectIndex, x, y)
	end
end

function UIPrefabObject:setAnchorMax(x, y)
	if self.prefabHelper then
		self.prefabHelper:SetAnchorMax(self.objectIndex, x, y)
	end
end

function UIPrefabObject:setSizeDelta(x, y)
	if self.prefabHelper then
		self.prefabHelper:SetSizeDelta(self.objectIndex, x, y)
	else
		BaseObject.setSizeDelta(self, x, y)
	end
end

function UIPrefabObject:setSizeDeltaX(x)
	if self.prefabHelper then
		self.prefabHelper:SetSizeDeltaX(self.objectIndex, x)
	else
		BaseObject.setSizeDeltaX(self, x)
	end
end

function UIPrefabObject:setSizeDeltaY(y)
	if self.prefabHelper then
		self.prefabHelper:SetSizeDeltaY(self.objectIndex, y)
	else
		BaseObject.setSizeDeltaY(self, y)
	end
end

function UIPrefabObject:addSizeDelta(x, y)
	if self.prefabHelper then
		self.prefabHelper:AddSizeDelta(self.objectIndex, x, y)
	else
		BaseObject.addSizeDelta(self, x, y)
	end
end

function UIPrefabObject:getSizeDelta()
	if self.prefabHelper then
		return self.prefabHelper:GetSizeDelta(self.objectIndex)
	else
		return BaseObject.getSizeDelta(self)
	end
end

function UIPrefabObject:fastGetSizeDelta()
	if self.prefabHelper then
		self.prefabHelper:CacheSizeDelt(self.objectIndex)
		return self.prefabHelper.PositionX, self.prefabHelper.PositionY
	else
		local sizeDelta = self:getSizeDelta()
		return sizeDelta.x, sizeDelta.y
	end
end

function UIPrefabObject:fastGetSizeDeltaY()
	if self.prefabHelper then
		self.prefabHelper:CacheSizeDelt(self.objectIndex)
		return self.prefabHelper.PositionY
	else
		local sizeDelta = self:getSizeDelta()
		return sizeDelta.y
	end
end

function UIPrefabObject:getRectWidth()
	if self.prefabHelper then
		return self.prefabHelper:GetRectWidth(self.objectIndex)
	else
		local transform = self:getTransform()
		return transform.rect.width
	end
end

function UIPrefabObject:getRectHeight()
	if self.prefabHelper then
		return self.prefabHelper:GetRectHeight(self.objectIndex)
	else
		local transform = self:getTransform()
		return transform.rect.height
	end
end

function UIPrefabObject:setPosition(x, y, z)
	if self.prefabHelper then
		self.prefabHelper:SetPosition(self.objectIndex, x, y, z)
	else
		BaseObject.setPosition(self, x, y, z)
	end
end

function UIPrefabObject:addPosition(x, y, z)
	if self.prefabHelper then
		self.prefabHelper:AddPosition(self.objectIndex, x, y, z)
	else
		BaseObject.addPosition(self, x, y, z)
	end
end

function UIPrefabObject:setLocalPosition(x, y, z)
	if self.prefabHelper then
		self.prefabHelper:SetLocalPosition(self.objectIndex, x, y, z)
	else
		BaseObject.setLocalPosition(self, x, y, z)
	end
end

function UIPrefabObject:setLocalPositionX(x)
	if self.prefabHelper then
		self.prefabHelper:SetLocalPositionX(self.objectIndex, x)
	else
		BaseObject.setLocalPositionX(self, x)
	end
end

function UIPrefabObject:setLocalPositionY(y)
	if self.prefabHelper then
		self.prefabHelper:SetLocalPositionY(self.objectIndex, y)
	else
		BaseObject.setLocalPositionY(self, y)
	end
end

function UIPrefabObject:addLocalPosition(x, y, z)
	if self.prefabHelper then
		self.prefabHelper:AddLocalPosition(self.objectIndex, x, y, z)
	else
		BaseObject.addLocalPosition(self, x, y, z)
	end
end

function UIPrefabObject:fastGetLocalPosition()
	if self.prefabHelper then
		self.prefabHelper:CacheLocalPosition(self.objectIndex)
		return self.prefabHelper.PositionX, self.prefabHelper.PositionY, self.prefabHelper.PositionZ
	else
		local position = self:getTransform().localPosition
		return position.x, position.y, position.z
	end
end

function UIPrefabObject:getlocalRotationZ()
	if self.prefabHelper then
		return self.prefabHelper:GetlocalRotationZ(self.objectIndex)
	else
		return 0
	end
end

function UIPrefabObject:setOffsetMin(x, y)
	if self.prefabHelper then
		self.prefabHelper:SetOffsetMin(self.objectIndex, x, y)
	else
		local transform = self:getTransform()
		Vector2.x = x
		Vector2.y = y
		transform.offsetMin = Vector2
	end
end

function UIPrefabObject:setOffsetMax(x, y)
	if self.prefabHelper then
		self.prefabHelper:SetOffsetMax(self.objectIndex, x, y)
	else
		local transform = self:getTransform()
		Vector2.x = x
		Vector2.y = y
		transform.offsetMax = Vector2
	end
end

function UIPrefabObject:setVisible(visible, scale)
	if visible then
		scale = scale or 1
		self:setLocalScale(scale, scale, scale)
	else
		self:setLocalScale(0, 0, 0)
	end
end

function UIPrefabObject:setLocalScale(x, y, z)
	if self.prefabHelper then
		self.prefabHelper:SetLocalScale(self.objectIndex, x, y, z)
	else
		BaseObject.setLocalScale(self, x, y, z)
	end
end

function UIPrefabObject:fastGetLocalScale()
	if self.prefabHelper then
		self.prefabHelper:CacheLocalScale(self.objectIndex)
		return self.prefabHelper.PositionX, self.prefabHelper.PositionY, self.prefabHelper.PositionZ
	else
		local localScale = self:getTransform().localScale
		return localScale.x, localScale.y, localScale.z
	end
end

function UIPrefabObject:addLocalScale(x, y, z)
	if self.prefabHelper then
		self.prefabHelper:AddLocalScale(self.objectIndex, x, y, z)
	else
		BaseObject.addLocalScale(self, x, y, z)
	end
end

function UIPrefabObject:setEulerAngles(x, y, z)
	if self.prefabHelper then
		self.prefabHelper:SetEulerAngles(self.objectIndex, x, y, z)
	else
		BaseObject.setEulerAngles(self, x, y, z)
	end
end

function UIPrefabObject:addEulerAngles(x, y, z)
	if self.prefabHelper then
		self.prefabHelper:AddEulerAngles(self.objectIndex, x, y, z)
	else
		BaseObject.addEulerAngles(self, x, y, z)
	end
end

function UIPrefabObject:setLocalEulerAngles(x, y, z)
	if self.prefabHelper then
		self.prefabHelper:SetLocalEulerAngles(self.objectIndex, x, y, z)
	else
		BaseObject.setLocalEulerAngles(self, x, y, z)
	end
end

function UIPrefabObject:addLocalEulerAngles(x, y, z)
	if self.prefabHelper then
		self.prefabHelper:AddLocalEulerAngles(self.objectIndex, x, y, z)
	else
		BaseObject.addLocalEulerAngles(self, x, y, z)
	end
end

--cell配合scrollrect使用监听滑动方向
function UIPrefabObject:addCellDragListener(func, bindSlideType)
	self._addTouchFlag = true
	local eventListener = self:getComponent(BF_UI_CELL_DRAG_EVNET)
	if eventListener == nil then
		eventListener = self:addComponent(BF_UI_CELL_DRAG_EVNET)
	end
	self._touchEventCallback = func
	eventListener:AddTouchEventListener(function(eventType, x, y)
		self:_onCellDragEvent(eventType, x, y)
	end, bindSlideType)
end

function UIPrefabObject:_onCellDragEvent(eventType, x, y)
	if self._touchEventCallback then
		self._touchEventCallback(eventType, x, y)
	end
	self:_handleLongPressEvent(eventType, x, y)
end

function UIPrefabObject:addDragListener(func)
	self._addTouchFlag = true
	local eventListener = self:getComponent(BF_UI_TOUCH_EVENT)
	if eventListener == nil then
		eventListener = self:addComponent(BF_UI_DRAG_EVENT)
	end
	self._touchEventCallback = func
	eventListener:AddTouchEventListener(function(eventType, x, y)
		self:_onDragEvent(eventType, x, y)
	end)
end

function UIPrefabObject:_onDragEvent(eventType, x, y)
	if self._touchEventCallback then
		self._touchEventCallback(eventType, x, y)
	end
	self:_handleLongPressEvent(eventType, x, y)
end

function UIPrefabObject:addTouchListener(func)
	self._addTouchFlag = true
	local eventListener = self:getComponent(BF_UI_TOUCH_EVENT)
	if eventListener == nil then
		eventListener = self:addComponent(BF_UI_TOUCH_EVENT)
	end
	self._touchEventCallback = func
	eventListener:AddTouchEventListener(function(eventType, x, y)
		self:_onTouchEvent(eventType, x, y)
	end)
end

function UIPrefabObject:_onTouchEvent(eventType, x, y)
	if self._touchEventCallback then
		self._touchEventCallback(eventType, x, y)
	end
	self:_handleLongPressEvent(eventType, x, y)
end

function UIPrefabObject:addClickListener(func, clickSound)
	self._addTouchFlag = true
	local eventListener = self:getComponent(BF_UI_TOUCH_EVENT)
	if eventListener == nil then
		eventListener = self:addComponent(BF_UI_TOUCH_EVENT)
	end
	self._touchEventCallback = func
	eventListener:AddTouchEventListener(function(eventType, x, y)
		self:_onClickEvent(eventType, x, y, clickSound)
	end)
end

function UIPrefabObject:_onClickEvent(eventType, x, y, clickSound)
	if self._touchEventCallback and eventType == GConst.TOUCH_EVENT.UP_INSIDE then
		if self.isShowClickAnimation == nil then
			local eventListener = self:getComponent(BF_UI_TOUCH_EVENT)
			if eventListener then
				self.isShowClickAnimation = eventListener:GetShowClickAnimation()
			end
		end
		if self.isShowClickAnimation then
			clickSound = clickSound or GConst.CLICK_SOUND.NORMAL
			local audioPath = AudioManager.CLICK_ID[clickSound]
			if audioPath then
				AudioManager:playEffect(audioPath)
			end
		end
		self._touchEventCallback(eventType, x, y)
	end
	self:_handleLongPressEvent(eventType, x, y)
end

function UIPrefabObject:addLongPressListener(func, time)
	self._addTouchFlag = true
	self._longPressTime = time or DELAULT_LONG_PRESS_TIME
	self._longPressCallback = func
	if self._touchEventCallback == nil then
		local eventListener = self:getComponent(BF_UI_TOUCH_EVENT)
		if eventListener == nil then
			eventListener = self:addComponent(BF_UI_TOUCH_EVENT)
		end
		eventListener:AddTouchEventListener(function(eventType, x, y)
			self:_onTouchEvent(eventType, x, y)
		end)
	end
end

function UIPrefabObject:_handleLongPressEvent(eventType, x, y)
	if self._longPressCallback then
		if eventType == GConst.TOUCH_EVENT.DOWN then
			if self._longPressSchedulerId then
				self:unscheduleGlobal(self._longPressSchedulerId)
			end
			self._longPressSchedulerId = self:performWithDelayGlobal(function()
				self._longPressSchedulerId = nil
				if self._longPressCallback then
					self._longPressCallback()
				end
			end, self._longPressTime)
		elseif eventType ~= GConst.TOUCH_EVENT.DRAG then
			if self._longPressSchedulerId then
				self:unscheduleGlobal(self._longPressSchedulerId)
				self._longPressSchedulerId = nil
			end
		end
	end
end

function UIPrefabObject:removeTouchListener()
	local eventListener = self:getComponent(BF_UI_TOUCH_EVENT)
	if eventListener then
		eventListener:RemoveEventListener()
	end
	self._addTouchFlag = false

	self._longPressTime = nil
	self._longPressCallback = nil
end

function UIPrefabObject:removeClickListener()
	self:removeTouchListener()
end

function UIPrefabObject:checkHrefLink(x, y)
	local uiCamera = UIManager:getUICameraComponent()
	local textCom = self:getComponent(GConst.TYPEOF_UNITY_CLASS.UI_TEXT_MESH_PRO)
	local hrefId = CS.TMPro.TMP_TextUtilities.FindIntersectingLink(textCom, CS.UnityEngine.Vector3(x, y, 0), uiCamera)
	return hrefId
end

function UIPrefabObject:setClickAnimation(enable)
	local eventListener = self:getComponent(BF_UI_TOUCH_EVENT)
	if eventListener then
		self.isShowClickAnimation = enable
		eventListener:SetShowClickAnimation(enable)
	end
end

function UIPrefabObject:stopClickAnimation()
	local eventListener = self:getComponent(BF_UI_TOUCH_EVENT)
	if eventListener then
		eventListener:StopTouchAnimation()
	end
end

function UIPrefabObject:setTouchEnable(enable)
	local maskableGraphic = self:getComponent(UI_MASKABLE_GRAPHIC)
	if maskableGraphic then
		maskableGraphic.raycastTarget = enable
	end
	local eventListener = self:getComponent(BF_UI_TOUCH_EVENT)
	if eventListener then
		eventListener:SetTouchEnable(enable)
	end
end

function UIPrefabObject:setLanguageSprite(atlasName, spriteName, callback, com)
	if string.isEmptyOrNil(atlasName) then
		Logger.logError("atlasName 为空!!")
		return
	end
	local languageName = I18N:getCurLanguage()
	local name = spriteName .. "_" .. languageName
	local path, _ = string.gsub(atlasName, "/atlas/", "/textures/")
	local spritePath = string.sub(path, 1, -7) .. "/" .. name .. ".png"
	if not ResourceManager:containsAsset(spritePath) then
		languageName = I18N:getFallbackLanguage()
		name = spriteName .. "_" .. languageName
		spritePath = string.sub(path, 1, -7) .. "/" .. name .. ".png"
		if not ResourceManager:containsAsset(spritePath) then
			Logger.logError("fallback language " .. languageName .. " 不包含 " .. spritePath)
			return
		end
	end
	self:setSprite(atlasName, name, callback, com)
end

function UIPrefabObject:setSprite(atlasPath, spriteName, callback, com)
	self:setSpriteHash(atlasPath, hash(spriteName), callback, com)
end

function UIPrefabObject:setSpriteHash(atlasPath, spriteHashName, callback, com)
	com = com or self:getComponent(GConst.TYPEOF_UNITY_CLASS.UI_IMAGE) or self:getComponent(GConst.TYPEOF_UNITY_CLASS.BF_SLIDER)
	if not com then
		return
	end
	if not self.resMap then
		self.resMap = {}
	end
	if not self.resMap[atlasPath] then
		TextureManager:loadAtlas(self, atlasPath, function(path, assets)
			if self.resMap[atlasPath] then
				TextureManager:unloadAtlas(atlasPath)
			else
				self.resMap[atlasPath] = assets
			end
			local sprite = assets:GetSprite(spriteHashName)
			if sprite then
				com.sprite = sprite
			else
				com.sprite = nil
				Logger.logError("图集%s丢失精灵", atlasPath)
			end

			if callback then
				callback(com)
			end
		end)
	else
		local sprite = self.resMap[atlasPath]:GetSprite(spriteHashName)
		if sprite then
			com.sprite = sprite
			if callback then
				callback(com)
			end
		else
			com.sprite = nil
			Logger.logError("图集%s丢失精灵", atlasPath)
		end
	end
end

function UIPrefabObject:setTexture(texturePath, callback)
	local rawImage = self:getComponent(GConst.TYPEOF_UNITY_CLASS.UI_RAW_IMAGE)
	if not rawImage then
		return
	end

	if not self.resMap then
		self.resMap = {}
	end

	if self.resMap[texturePath] then
		rawImage.texture = self.resMap[texturePath]
		if callback then
			callback(rawImage)
		end
	else
		TextureManager:loadTextureAsync(self, texturePath,function (assetsPath, texture)
			if self.resMap[assetsPath] then
				TextureManager:unLoadTexture(texturePath)
			else
				self.resMap[assetsPath] = texture
			end
			rawImage.texture = texture
			if callback then
				callback(rawImage)
			end
		end)
	end
end

function UIPrefabObject:setText(value, component)
	--其他textcompnent在外部获取
	component = component or self:getComponent(GConst.TYPEOF_UNITY_CLASS.UI_TEXT_MESH_PRO)

	if component then
		component.text = value
	else
		Logger.logWarning("can't find text component!")
	end
end

function UIPrefabObject:addRedPoint(offsetX, offsetY, scale, iconName, count, native)
	if not self.redPoint then
		if not self.loadRpOver then
			self.loadRpOver = true
			if self:isDestroyed() or CS.BF.Utils.IsNull(self:getGameObject()) then
				return
			end
			UIPrefabManager:loadUIWidgetAsync("assets/prefabs/ui/common/red_point_cell.prefab", self, function(prefabObject)
				self.redPoint = prefabObject
				prefabObject:initPrefabHelper()
				local uiMap = prefabObject:genAllChildren()
				self.redPoint:setAnchoredPosition(offsetX or 0, offsetY or 0)
				self.redPoint:setLocalScale(scale, scale, scale)
				iconName = iconName or "common_point"
				self.redPoint:setSprite(GConst.ATLAS_PATH.COMMON, iconName)
				GFunc.getShakeSeq(self.redPoint, false, scale, true)
				if native then
					self.redPoint:getComponent(GConst.TYPEOF_UNITY_CLASS.UI_IMAGE):SetNativeSize()
				end
				self.redPointCountTx = uiMap["red_point_cell.count_tx"]
				if count then
					self.redPointCountTx:setText(count)
				else
					self.redPointCountTx:setText("")
				end
			end)
		end
	else
		iconName = iconName or "common_point"
		self.redPoint:setSprite(GConst.ATLAS_PATH.COMMON, iconName)
		self.redPoint:setAnchoredPosition(offsetX or 0, offsetY or 0)
		self.redPoint:setActive(true)
		if native then
			self.redPoint:getComponent(GConst.TYPEOF_UNITY_CLASS.UI_IMAGE):SetNativeSize()
		end

		if self.redPointCountTx then
			if count then
				self.redPointCountTx:setText(count)
			else
				self.redPointCountTx:setText("")
			end
		end
	end
end

function UIPrefabObject:removeRedPoint()
	if self.redPoint then
		self.redPoint:setActive(false)
	end
end

function UIPrefabObject:addAdPoint(offsetX, offsetY, scale)
	if not self.adPoint then
		if not self.loadAdOver then
			self.loadAdOver = true
			UIPrefabManager:loadUIWidgetAsync("assets/prefabs/ui/common/ad_point_cell.prefab", self, function(prefabObject)
				self.adPoint = prefabObject
				prefabObject:initPrefabHelper()
				self.adPoint:setAnchoredPosition(offsetX or 0, offsetY or 0)
				GFunc.setAdsSprite(self.adPoint)
				self.adPoint:setLocalScale(scale, scale, scale)
			end)
		end
	else
		GFunc.setAdsSprite(self.adPoint)
		self.adPoint:setAnchoredPosition(offsetX or 0, offsetY or 0)
		self.adPoint:setActive(true)
	end
end

function UIPrefabObject:removeAdPoint()
	if self.adPoint then
		self.adPoint:setActive(false)
	end
end

function UIPrefabObject:setGraphicFlip(horizontal, vertical)
	local component = self:getComponent(GConst.TYPEOF_UNITY_CLASS.BF_GRAPHIC_FLIP)
	if component then
		component.horizontal = horizontal or false
		component.vertical = vertical or false
	else
		Logger.logWarning("can't find BF_GRAPHIC_FLIP component!")
	end
end

function UIPrefabObject:onDestroy()
	if self.resMap then
		for assetPath, _ in pairs(self.resMap) do
			ResourceManager:unload(assetPath)
		end
		self.resMap = nil
	end
	if self._addTouchFlag then
		self._touchEventCallback = nil
		self._longPressCallback = nil
		if self._longPressSchedulerId then
			self:unscheduleGlobal(self._longPressSchedulerId)
			self._longPressSchedulerId = nil
		end
	end
	self.redPoint = nil
	self.loadRpOver = nil
	self.prefabHelper = nil
	BaseObject.onDestroy(self)
	self.childMap = nil
end

function UIPrefabObject:setImageGray(grey)
	local com = self:getComponent(GConst.TYPEOF_UNITY_CLASS.UI_IMAGE)
	if not com then
		return
	end
	Color4.r = 1
	if grey then
		Color4.g = 0
		self:setTouchEnable(false)
	else
		Color4.g = 1
		self:setTouchEnable(true)
	end
	Color4.b = 1
	Color4.a = 1
	com.color = Color4
	return true
end

function UIPrefabObject:setScrollRectCellName(nameIndex)
	if self.prefabHelper then
		self.prefabHelper:SetScrollRectCellName(self.objectIndex, nameIndex)
	else
		BaseObject.setScrollRectCellName(self, nameIndex)
	end
end

return UIPrefabObject