local RenderConst = require "app/global/render_const"

local BFRenderMgr = CS.BF.BFMain.Instance.RenderMgr
local RenderManager = {}

RenderManager.POST_EFFECT_TYPE = {
    BLOOM = 1,
    VIVID_BLOOM = 2,
    FXAA = 4,
}

local SUPPORTS_INSTANCING = CS.UnityEngine.SystemInfo.supportsInstancing

local SHADER_VARIANT_PATH = "assets/arts/shaders/shader_variants.shadervariants"
local UI_DEFAULT_MAT_PATH = "assets/arts/materials/ui/ui_default.mat"
local UI_TUTORIAL_MAT_PATH = "assets/arts/materials/ui/ui_tutorial.mat"
local MESH_OUTLINE_FILL_MAT_PATH = "assets/arts/materials/mesh/outline_fill.mat"
local MESH_OUTLINE_MASK_MAT_PATH = "assets/arts/materials/mesh/outline_mask.mat"
local BLUR_MAT_PATH = "assets/arts/materials/post_effect/blur.mat"
local VIVID_BLOOM_MAT_PATH = "assets/arts/materials/post_effect/vivid_bloom.mat"
local BLIT_COPY_MAT_PATH = "assets/arts/materials/post_effect/blit_copy.mat"
local FXAA_MAT_PATH = "assets/arts/materials/post_effect/fxaa.mat"
local RADIAL_BLUR_MAT_PATH = "assets/arts/materials/post_effect/radial_blur.mat"

local TypeOfShaderVariantCollection = typeof(CS.UnityEngine.ShaderVariantCollection)
local TypeOfMaterial = typeof(CS.UnityEngine.Material)
local TypeOfPostEffectBehaviour = typeof(CS.BF.PostEffectBehaviour)

function RenderManager:initRender(callBack)
    if self.renderInited then
        callBack()
        return
    end
    self.renderInited = true
    if USE_AB then
        local time = os.clock()
        ResourceManager:loadOriginAssetAsync(SHADER_VARIANT_PATH, TypeOfShaderVariantCollection, function(assetPath, asset)
            asset:WarmUp()
            self:initMaterials(callBack)
            Logger.log("init render use time " .. (os.clock() - time))
        end)
    else
        self:initMaterials(callBack)
    end
end

function RenderManager:initMaterials(callback)
    local loadCount = 4

    ResourceManager:loadOriginAssetAsync(UI_DEFAULT_MAT_PATH, TypeOfMaterial, function(path, material)
        self.uiDefaultMat = material
        BFRenderMgr:SetUIDefaultMat(self.uiDefaultMat)
        loadCount = loadCount - 1
        if loadCount == 0 then
            callback()
        end
    end)

    ResourceManager:loadOriginAssetAsync(UI_TUTORIAL_MAT_PATH, TypeOfMaterial, function(path, material)
        self.uiTutorialMat = material
        BFRenderMgr:SetUITutorialMat(self.uiTutorialMat)
        loadCount = loadCount - 1
        if loadCount == 0 then
            callback()
        end
    end)

    ResourceManager:loadOriginAssetAsync(MESH_OUTLINE_FILL_MAT_PATH, TypeOfMaterial, function(path, material)
        self.meshOutlineFillMat = material
        BFRenderMgr:SetMeshOutlineFillMat(self.meshOutlineFillMat)
        loadCount = loadCount - 1
        if loadCount == 0 then
            callback()
        end
    end)

    ResourceManager:loadOriginAssetAsync(MESH_OUTLINE_MASK_MAT_PATH, TypeOfMaterial, function(path, material)
        self.meshOutlineMaskMat = material
        BFRenderMgr:SetMeshOutlineMaskMat(self.meshOutlineMaskMat)
        loadCount = loadCount - 1
        if loadCount == 0 then
            callback()
        end
    end)

    -- ResourceManager:loadOriginAssetAsync(BLUR_MAT_PATH, TypeOfMaterial, function(path, material)
    --     self.blurMat = material
    --     BFRenderMgr:SetBlurMat(self.blurMat)
    --     loadCount = loadCount - 1
    --     if loadCount == 0 then
    --         callback()
    --     end
    -- end)

    -- ResourceManager:loadOriginAssetAsync(VIVID_BLOOM_MAT_PATH, TypeOfMaterial, function(path, material)
    --     self.vividBloomMat = material
    --     BFRenderMgr:SetVividBloomMat(self.vividBloomMat)
    --     loadCount = loadCount - 1
    --     if loadCount == 0 then
    --         callback()
    --     end
    -- end)

    -- ResourceManager:loadOriginAssetAsync(BLIT_COPY_MAT_PATH, TypeOfMaterial, function(path, material)
    --     self.blitCopyMat = material
    --     BFRenderMgr:SetBlitCopyMat(self.blitCopyMat)
    --     loadCount = loadCount - 1
    --     if loadCount == 0 then
    --         callback()
    --     end
    -- end)

    -- ResourceManager:loadOriginAssetAsync(FXAA_MAT_PATH, TypeOfMaterial, function(path, material)
    --     self.fxaaMat = material
    --     BFRenderMgr:SetFxaaMat(self.fxaaMat)
    --     loadCount = loadCount - 1
    --     if loadCount == 0 then
    --         callback()
    --     end
    -- end)

    -- ResourceManager:loadOriginAssetAsync(RADIAL_BLUR_MAT_PATH, TypeOfMaterial, function(path, material)
    --     self.radialBlurMat = material
    --     BFRenderMgr:SetRadialBlur(self.radialBlurMat)
    --     loadCount = loadCount - 1
    --     if loadCount == 0 then
    --         callback()
    --     end
    -- end)
end

function RenderManager:loadShaderAsync(shaderPath, callBack)
    ResourceManager:loadOriginAssetAsync(shaderPath, GConst.TYPEOF_UNITY_CLASS.SHADER, callBack)
end

function RenderManager:unloadShader(shaderPath, immediately)
    ResourceManager:unload(shaderPath, immediately)
end

function RenderManager:loadMaterialAsync(materialPath, callBack)
    ResourceManager:loadOriginAssetAsync(materialPath, GConst.TYPEOF_UNITY_CLASS.MATERIAL, callBack)
end

function RenderManager:unloadMaterial(materialPath, immediately)
    ResourceManager:unload(materialPath, immediately)
end

function RenderManager:closePostEffect(effectType, camera)
    BFRenderMgr:ClosePostEffect(effectType, camera)
end

function RenderManager:closeFxaa(camera)
    self:closePostEffect(RenderManager.POST_EFFECT_TYPE.FXAA, camera)
end

---- 传入一张图，返回高斯模糊图
function RenderManager:getBlurTexture(texture, width, height, iteration)
    if not iteration then
        iteration = 4
    end

    if not self.blurSizeID then
       self.blurSizeID = CS.UnityEngine.Shader.PropertyToID("_BlurSize")
    end

    local CSRenderTexture = CS.UnityEngine.RenderTexture
    local CSGraphics = CS.UnityEngine.Graphics
    local rt0 = CSRenderTexture.GetTemporary(width, height)

    for i = 1, iteration do
        self.blurMat:SetFloat(self.blurSizeID, i)
        local rt1 = CSRenderTexture.GetTemporary(width, height)
        if i == 1 then
            CSGraphics.Blit(texture, rt1, self.blurMat, 0)
        else
            CSGraphics.Blit(rt0, rt1, self.blurMat, 0)
        end
        CSRenderTexture.ReleaseTemporary(rt0)
        rt0 = CSRenderTexture.GetTemporary(width, height)
        CSGraphics.Blit(rt1, rt0, self.blurMat, 1)
        CSRenderTexture.ReleaseTemporary(rt1)
    end
    return rt0
end

---- 是否支持gpu instancing
function RenderManager:isSupportInstancing()
    return SUPPORTS_INSTANCING
end

function RenderManager:getUITutorialMat()
    return self.uiTutorialMat
end

return RenderManager