local UIBaseComponent = BaseClass("UIBaseComponent")
local ResourceManager = CS.GameEntry.Resource
local RectTransformCSType = typeof(CS.UnityEngine.RectTransform)
local __init = function(self, holder, var_arg)
  self.view = nil
  self.holder = holder
  self.transform = nil
  self.gameObject = nil
  self.rectTransform = nil
  self.__name = nil
  self.__var_arg = var_arg
  self.activeSelf = false
  self.activeCached = nil
  self.goInstances = nil
  self.initActiveSelf = nil
  self.alreadyLoaded = false
  self.dynamicNodeDict = nil
end
local Reinit = function(self, holder, var_arg)
  __init(self, holder, var_arg)
end
local __delete = function(self)
  if self.gameObject ~= nil then
    self:OnDestroy()
  else
    self.holder = nil
  end
end
local lua_type = type
local csharp_IsNull = IsNull
local OnCreate = function(self)
  local holderTrans = self.holder and self.holder.transform or nil
  if self._class_type == UILayerComponent then
    self.view = nil
  else
    local now_holder = self.holder
    while now_holder ~= nil do
      if now_holder._class_type == UILayerComponent then
        self.view = self
        break
      elseif now_holder.view ~= nil then
        self.view = now_holder.view
        break
      end
      now_holder = now_holder.holder
    end
  end
  local argType = lua_type(self.__var_arg)
  if argType == "string" then
    local obj = holderTrans:Find(self.__var_arg)
    if csharp_IsNull(obj) then
      Logger.LogError("UI Comp Create -> holderTrans:Find(self.__var_arg) is null! " .. self.__var_arg)
    end
    self.gameObject = obj.gameObject
    self.alreadyLoaded = true
  elseif argType == "userdata" then
    self.gameObject = self.__var_arg
    self.alreadyLoaded = true
  else
    error("OnCreate : error params list! " .. argType .. " " .. tostring(self.__var_arg))
  end
  if self.initActiveSelf ~= nil then
    self.gameObject:SetActive(self.initActiveSelf)
    self.initActiveSelf = nil
  end
  self.activeSelf = self.gameObject.activeSelf
  self.__name = self.gameObject.name
end
local getter_transform = function(self)
  if self.alreadyLoaded then
    self.transform = self.gameObject.transform
    return self.transform
  end
  return nil
end
local getter_rectTransform = function(self)
  if self.alreadyLoaded then
    self.rectTransform = self.gameObject:GetComponent(RectTransformCSType)
    return self.rectTransform
  end
  return nil
end
local OnEnable = function(self)
end
local GetName = function(self)
  return self.__name
end
local SetName = function(self, name, toUnity)
  if self.holder ~= nil and self.holder.OnComponentSetName ~= nil then
    self.holder:OnComponentSetName(self, name)
  end
  self.__name = name
  if toUnity or Config.Debug then
    if IsNull(self.gameObject) then
      Logger.LogError("gameObject null, you maybe have to wait for loading prefab finished!")
      return
    end
    self.gameObject.__name = name
  end
end
local SetActive = function(self, active)
  if active then
    if self:GetActiveInHierarchy() then
      return
    end
  elseif not self:GetActiveInHierarchy() then
    if self.gameObject then
      if self.activeSelf ~= false then
        self.gameObject:SetActive(false)
      end
    else
      self:SetInitActiveSelf(false)
    end
    self.activeSelf = false
    return
  end
  self.activeSelf = active
  self.activeCached = active
  if self.gameObject ~= nil then
    self.gameObject:SetActive(active)
    if active then
      self:OnEnable()
    else
      self:OnDisable()
    end
  else
    self:SetInitActiveSelf(active)
    Logger.Log("self.gameObject nil, " .. tostring(__var_arg))
  end
end
local GetActive = function(self)
  return self.activeSelf
end
local GetActiveInHierarchy = function(self)
  local activeCached = self.activeCached
  if activeCached ~= nil then
    return activeCached
  end
  activeCached = self.activeSelf and (self.holder == nil or lua_type(self.holder.GetActiveInHierarchy) == "function" and self.holder:GetActiveInHierarchy())
  self.activeCached = activeCached
  return activeCached
end
local SetInitActiveSelf = function(self, active)
  self.initActiveSelf = active
end
local OnDisable = function(self)
end
local __OnFrameworkDestroy = function(self)
end
local OnDestroy = function(self)
  if self.holder ~= nil and self.holder.OnComponentDestroy ~= nil then
    self.holder:OnComponentDestroy(self)
  end
  if self.dynamicNodeDict then
    for _, node in ipairs(self.dynamicNodeDict) do
      if node and type(node.Delete) == "function" then
        pcall(node.Delete, node)
      end
    end
  end
  self.dynamicNodeDict = nil
  self.view = nil
  self.holder = nil
  self.transform = nil
  self.gameObject = nil
  self.rectTransform = nil
  self.__name = nil
  self.alreadyLoaded = false
  if self.goInstances then
    for req, t in pairs(self.goInstances) do
      req:Destroy()
    end
  end
end
local GameObjectInstantiateAsync = function(self, prefabPath, onComplete)
  local req = ResourceManager:InstantiateAsync(prefabPath)
  req:completed("+", function()
    if CommonUtil and CommonUtil.IsArabicAutoMirrorOpen() and not req.isUseCache then
      CS.ArabicMirror.MirrorEntry(true, true, req.gameObject)
    end
    if onComplete then
      onComplete(req)
    end
  end)
  if not self.goInstances then
    self.goInstances = {}
  end
  self.goInstances[req] = "InstanceRequest"
  return req
end
local GameObjectDestroy = function(self, req)
  if not self.goInstances then
    return
  end
  local t = self.goInstances[req]
  if t == "InstanceRequest" then
    self.goInstances[req] = nil
    req:Destroy()
  end
end
local DestroyChildNode = function(childTransform)
  if childTransform == nil then
    return
  end
  local childCnt = childTransform.transform.childCount
  for i = 0, childCnt - 1 do
    local child = childTransform.transform:GetChild(i)
    CS.UnityEngine.GameObject.Destroy(child.gameObject)
  end
end
local DestroyChildNodeExceptIndex = function(childTransform, instanceId)
  if childTransform == nil then
    return
  end
  local childCnt = childTransform.transform.childCount
  for i = 0, childCnt - 1 do
    local child = childTransform.transform:GetChild(i)
    if instanceId == nil or child:GetInstanceID() ~= instanceId then
      CS.UnityEngine.GameObject.Destroy(child.gameObject)
    end
  end
end
local DestroyChildNodeExceptIndices = function(childTransform, instanceIds)
  if childTransform == nil then
    return
  end
  local childCnt = childTransform.transform.childCount
  for i = 0, childCnt - 1 do
    local child = childTransform.transform:GetChild(i)
    local childId = child:GetInstanceID()
    if string.IsNullOrEmpty(instanceIds) or not instanceIds[childId] then
      CS.UnityEngine.GameObject.Destroy(child.gameObject)
    end
  end
end
local SetEnabled = function(self, value)
  if CS.UnityEngine.Application.isEditor then
    UIUtil.ShowTips("[\231\188\150\232\190\145\229\153\168] \230\178\161\230\156\137\229\174\158\231\142\176 SetEnabled \230\150\185\230\179\149\239\188\129")
    Logger.LogWarning("\230\178\161\230\156\137\229\174\158\231\142\176 SetEnabled \230\150\185\230\179\149")
  end
end
local SetPositionXYZ = function(self, x, y, z)
  self.rectTransform:Set_position(x, y, z)
end
local GetPositionXYZ = function(self)
  return self.rectTransform:Get_position()
end
local SetPosition = function(self, v)
  self.rectTransform:Set_position(v.x, v.y, v.z)
end
local GetPosition = function(self)
  local x, y, z = self.rectTransform:Get_position()
  return Vector3.New(x, y, z)
end
local SetLocalPositionXYZ = function(self, x, y, z, skipArabicMirror)
  if not skipArabicMirror and CommonUtil and x then
    x = x * CommonUtil.ArabicAutoMirrorFactor()
  end
  self.rectTransform:Set_localPosition(x, y, z)
end
local GetLocalPositionXYZ = function(self, skipArabicMirror)
  local x, y, z = self.rectTransform:Get_localPosition()
  if not skipArabicMirror and CommonUtil and x then
    x = x * CommonUtil.ArabicAutoMirrorFactor()
  end
  return x, y, z
end
local SetLocalPosition = function(self, v, skipArabicMirror)
  local pos = DeepCopy(v)
  if not skipArabicMirror and CommonUtil and pos and pos.x then
    pos.x = pos.x * CommonUtil.ArabicAutoMirrorFactor()
  end
  self.rectTransform:Set_localPosition(pos.x, pos.y, pos.z)
end
local GetLocalPosition = function(self, skipArabicMirror)
  local x, y, z = self.rectTransform:Get_localPosition()
  if not skipArabicMirror and CommonUtil and x then
    x = x * CommonUtil.ArabicAutoMirrorFactor()
  end
  return Vector3.New(x, y, z)
end
local SetLocalScaleXYZ = function(self, x, y, z)
  self.rectTransform:Set_localScale(x, y, z)
end
local GetLocalScaleXYZ = function(self)
  return self.rectTransform:Get_localScale()
end
local SetLocalScale = function(self, v)
  self.rectTransform:Set_localScale(v.x, v.y, v.z)
end
local GetLocalScale = function(self)
  local x, y, z = self.rectTransform:Get_localScale()
  return Vector3.New(x, y, z)
end
local SetEulerAnglesXYZ = function(self, x, y, z)
  self.rectTransform:Set_eulerAngles(x, y, z)
end
local GetEulerAnglesXYZ = function(self)
  return self.rectTransform:Get_eulerAngles()
end
local SetEulerAngles = function(self, v)
  self.rectTransform:Set_eulerAngles(v.x, v.y, v.z)
end
local GetEulerAngles = function(self)
  local x, y, z = self.rectTransform:Get_eulerAngles()
  return Vector3.New(x, y, z)
end
local SetAnchorMinXY = function(self, x, y)
  self.rectTransform:Set_anchorMin(x, y)
end
local GetAnchorMinXY = function(self)
  return self.rectTransform:Get_anchorMin()
end
local SetAnchorMin = function(self, v)
  self.rectTransform:Set_anchorMin(v.x, v.y)
end
local GetAnchorMin = function(self)
  local x, y = self.rectTransform:Get_anchorMin()
  return Vector2.New(x, y)
end
local SetAnchorMaxXY = function(self, x, y)
  self.rectTransform:Set_anchorMax(x, y)
end
local GetAnchorMaxXY = function(self)
  return self.rectTransform:Get_anchorMax()
end
local SetAnchorMax = function(self, v)
  self.rectTransform:Set_anchorMax(v.x, v.y)
end
local GetAnchorMax = function(self)
  local x, y = self.rectTransform:Get_anchorMax()
  return Vector2.New(x, y)
end
local SetOffsetMaxXY = function(self, x, y)
  self.rectTransform:Set_offsetMax(x, y)
end
local GetOffsetMaxXY = function(self)
  return self.rectTransform:Get_offsetMax()
end
local SetOffsetMax = function(self, v)
  self.rectTransform:Set_offsetMax(v.x, v.y)
end
local GetOffsetMax = function(self)
  local x, y = self.rectTransform:Get_offsetMax()
  return Vector2.New(x, y)
end
local SetOffsetMinXY = function(self, x, y)
  self.rectTransform:Set_offsetMin(x, y)
end
local GetOffsetMinXY = function(self)
  return self.rectTransform:Get_offsetMin()
end
local SetOffsetMin = function(self, v)
  self.rectTransform:Set_offsetMin(v.x, v.y)
end
local GetOffsetMin = function(self)
  local x, y = self.rectTransform:Get_offsetMin()
  return Vector2.New(x, y)
end
local SetAnchoredPosition = function(self, value, skipArabicMirror)
  local pos = DeepCopy(value)
  if not skipArabicMirror and CommonUtil and pos and pos.x then
    pos.x = pos.x * CommonUtil.ArabicAutoMirrorFactor()
  end
  self.rectTransform:Set_anchoredPosition(pos.x, pos.y)
end
local SetAnchoredPositionXY = function(self, x, y, skipArabicMirror)
  if not skipArabicMirror and CommonUtil and x then
    x = x * CommonUtil.ArabicAutoMirrorFactor()
  end
  self.rectTransform:Set_anchoredPosition(x, y)
end
local GetAnchoredPosition = function(self, skipArabicMirror)
  local x, y = self.rectTransform:Get_anchoredPosition()
  if not skipArabicMirror and CommonUtil and x then
    x = x * CommonUtil.ArabicAutoMirrorFactor()
  end
  return Vector2.New(x, y)
end
local GetAnchoredPositionX = function(self, skipArabicMirror)
  local x, y = self.rectTransform:Get_anchoredPosition()
  if not skipArabicMirror and CommonUtil and x then
    x = x * CommonUtil.ArabicAutoMirrorFactor()
  end
  return x
end
local GetAnchoredPositionY = function(self)
  local x, y = self.rectTransform:Get_anchoredPosition()
  return y
end
local GetSizeDelta = function(self)
  if not self.rectTransform then
    Logger.LogError(string.format("__UIException__ GetSizeDelta exception! rect transform is null. alreadyLoaded = %s", self.alreadyLoaded))
    return Vector2.zero
  end
  local x, y = self.rectTransform:Get_sizeDelta()
  return Vector2.New(x, y)
end

function UIBaseComponent:GetSizeDeltaXY()
  local x, y = self.rectTransform:Get_sizeDelta()
  return x, y
end

local SetSizeDelta = function(self, value)
  self.rectTransform:Set_sizeDelta(value.x, value.y)
end

function UIBaseComponent:SetSizeDeltaXY(x, y)
  self.rectTransform:Set_sizeDelta(x, y)
end

function UIBaseComponent:SetAsFirstSibling()
  self.transform:SetAsFirstSibling()
end

function UIBaseComponent:SetAsLastSibling()
  self.transform:SetAsLastSibling()
end

function UIBaseComponent:SetSiblingIndex(index)
  self.transform:SetSiblingIndex(index)
end

function UIBaseComponent:SetPivotXY(x, y)
  if not self.rectTransform then
    return
  end
  if not x or not y then
    return
  end
  self.rectTransform:Set_pivot(x, y)
end

function UIBaseComponent:SetPivotMiddle()
  if not self.rectTransform then
    return
  end
  self.rectTransform:Set_pivot(0.5, 0.5)
end

function UIBaseComponent:SetSizeDeltaY(y)
  local x = self:GetSizeDelta().x
  self.rectTransform:Set_sizeDelta(x, y)
end

function UIBaseComponent:SetSizeDeltaX(x)
  local y = self:GetSizeDelta().y
  self.rectTransform:Set_sizeDelta(x, y)
end

function UIBaseComponent:LoadComponentAsync(luaClassOrPath, prefabPath, parent, callback, callback_param, var_arg)
  local ret
  local result, errorMsg = pcall(function()
    local theParent = parent or self
    if theParent ~= nil and luaClassOrPath ~= nil then
      local transform = theParent.transform
      if IsNotNull(transform) then
        local luaClass = luaClassOrPath
        if type(luaClass) == "string" then
          luaClass = require(luaClassOrPath)
        end
        if luaClass ~= nil then
          ret = luaClass.New(self, transform, prefabPath, callback, callback_param, var_arg)
          if self.dynamicNodeDict == nil then
            self.dynamicNodeDict = {}
          end
          table.insert(self.dynamicNodeDict, ret)
        end
      end
    end
  end)
  if result == false then
    Logger.LogError("AsyncLoadComponent fail, error = " .. errorMsg)
  end
  return ret
end

function UIBaseComponent:RemoveAsyncComponent(luaClass)
  if self.dynamicNodeDict ~= nil and luaClass ~= nil and luaClass.instanceOf ~= nil and luaClass:instanceOf("UIAsyncContainer") then
    for index, cache in ipairs(self.dynamicNodeDict) do
      if cache == luaClass and type(cache.Delete) == "function" then
        pcall(cache.Delete, cache)
        pcall(function()
          table.remove(self.dynamicNodeDict, index)
        end)
        break
      end
    end
  end
end

UIBaseComponent.__init = __init
UIBaseComponent.Reinit = Reinit
UIBaseComponent.__delete = __delete
UIBaseComponent.OnCreate = OnCreate
UIBaseComponent.OnEnable = OnEnable
UIBaseComponent.GetName = GetName
UIBaseComponent.SetName = SetName
UIBaseComponent.SetActive = SetActive
UIBaseComponent.SetInitActiveSelf = SetInitActiveSelf
UIBaseComponent.GetActive = GetActive
UIBaseComponent.GetActiveInHierarchy = GetActiveInHierarchy
UIBaseComponent.OnDisable = OnDisable
UIBaseComponent.OnDestroy = OnDestroy
UIBaseComponent.__OnFrameworkDestroy = __OnFrameworkDestroy
UIBaseComponent.GameObjectInstantiateAsync = GameObjectInstantiateAsync
UIBaseComponent.GameObjectDestroy = GameObjectDestroy
UIBaseComponent.DestroyChildNode = DestroyChildNode
UIBaseComponent.DestroyChildNodeExceptIndex = DestroyChildNodeExceptIndex
UIBaseComponent.DestroyChildNodeExceptIndices = DestroyChildNodeExceptIndices
UIBaseComponent.SetEnabled = SetEnabled
UIBaseComponent.SetAnchoredPosition = SetAnchoredPosition
UIBaseComponent.SetAnchoredPositionXY = SetAnchoredPositionXY
UIBaseComponent.GetAnchoredPosition = GetAnchoredPosition
UIBaseComponent.GetAnchoredPositionX = GetAnchoredPositionX
UIBaseComponent.GetAnchoredPositionY = GetAnchoredPositionY
UIBaseComponent.GetSizeDelta = GetSizeDelta
UIBaseComponent.SetSizeDelta = SetSizeDelta
UIBaseComponent.SetPosition = SetPosition
UIBaseComponent.GetPosition = GetPosition
UIBaseComponent.SetPositionXYZ = SetPositionXYZ
UIBaseComponent.GetPositionXYZ = GetPositionXYZ
UIBaseComponent.SetLocalPosition = SetLocalPosition
UIBaseComponent.GetLocalPosition = GetLocalPosition
UIBaseComponent.SetLocalPositionXYZ = SetLocalPositionXYZ
UIBaseComponent.GetLocalPositionXYZ = GetLocalPositionXYZ
UIBaseComponent.SetLocalScale = SetLocalScale
UIBaseComponent.GetLocalScale = GetLocalScale
UIBaseComponent.SetLocalScaleXYZ = SetLocalScaleXYZ
UIBaseComponent.GetLocalScaleXYZ = GetLocalScaleXYZ
UIBaseComponent.SetEulerAngles = SetEulerAngles
UIBaseComponent.GetEulerAngles = GetEulerAngles
UIBaseComponent.SetEulerAnglesXYZ = SetEulerAnglesXYZ
UIBaseComponent.GetEulerAnglesXYZ = GetEulerAnglesXYZ
UIBaseComponent.SetAnchorMin = SetAnchorMin
UIBaseComponent.GetAnchorMin = GetAnchorMin
UIBaseComponent.SetAnchorMinXY = SetAnchorMinXY
UIBaseComponent.GetAnchorMinXY = GetAnchorMinXY
UIBaseComponent.SetAnchorMax = SetAnchorMax
UIBaseComponent.GetAnchorMax = GetAnchorMax
UIBaseComponent.SetAnchorMaxXY = SetAnchorMaxXY
UIBaseComponent.GetAnchorMaxXY = GetAnchorMaxXY
UIBaseComponent.SetOffsetMaxXY = SetOffsetMaxXY
UIBaseComponent.GetOffsetMaxXY = GetOffsetMaxXY
UIBaseComponent.SetOffsetMax = SetOffsetMax
UIBaseComponent.GetOffsetMax = GetOffsetMax
UIBaseComponent.SetOffsetMinXY = SetOffsetMinXY
UIBaseComponent.GetOffsetMinXY = GetOffsetMinXY
UIBaseComponent.SetOffsetMin = SetOffsetMin
UIBaseComponent.GetOffsetMin = GetOffsetMin
UIBaseComponent.getters.transform = getter_transform
UIBaseComponent.getters.rectTransform = getter_rectTransform
return UIBaseComponent
