---
--- Generated by EmmyLua(https://github.com/EmmyLua)
--- Created by HUAFEI2.
--- DateTime: 2020/5/27 17:08
---
local Cfg = ImportScript("ugc_common/script/cases/change_cloth/config.lua").Cfg;

UI_CHANGE_CLOTH = "ChangeClothUi";
local Ui = Ui or class(UI_CHANGE_CLOTH, LUiBase);
_G.UI_CHANGE_CLOTH = UI_CHANGE_CLOTH;

--[[
Ui = {
    m_bOpen = false;
    ...
}
--]]
local g_tRoleType = {
    [1] = 1, -- M2
    [2] = 2, -- F2
    [3] = 5, -- M1
    [4] = 6, -- F1
}

function Ui:ctor()
    self.m_bOpen = false;
    self.m_szName = UI_CHANGE_CLOTH;

    self.m_selectCharIdx = 0;
    self.m_selectPartIdx = 0;
    self.m_tbSelectedCharPartModel = {};
    self.m_imguiModelFilter = "";
    self.m_bEnableSD = true;
    self.m_bEnableHD = true;

    self.m_dt = self:GetDataTable();
    LOG_I("[ChangeClothUi  ctor]", self.m_dt.m_actor);

    self.m_tbCharList = Cfg:GetCharList();
    self.m_tbPartList = Cfg:GetPartList();

    self.m_szWndName = util.a2u8("换装");
    self.m_szCharComboName = util.a2u8("体型");
    self.m_szPartComboName = util.a2u8("部件");
    self.m_szRmvPartBtnName = util.a2u8("移除部件");
    self.m_szClearPartBtnName = util.a2u8("清除部件");
    self.m_szSModelChkBoxName = util.a2u8("简单资源");
    self.m_szHModelChkBoxName = util.a2u8("重制资源");
    self.m_szLoadSuitBtnName = util.a2u8("同名加载");
    self.m_curRole = nil;
end

function Ui:dtor()
    LOG_I("[ChangeClothUi  dtor]", self.m_dt.m_actor);
    --self.m_imguiModelFilter:Clear()
    
    if self.m_dt.m_actor ~= nil then
        g_ActorManager:DestroyActor(self.m_dt.m_actor);
        self.m_dt.m_actor = nil;
    end
end

function Ui:OnOpen()
    self:transport2Player();
    if self.m_dt.m_actor then
        self.m_dt.m_actor:SetVisible(true);
    end
end

function Ui:OnClose()
    if self.m_dt.m_actor then
        self.m_dt.m_actor:SetVisible(false);
    end
end

function Ui:GameDraw()
    ImGui.SetNextWindowSize(ImVec2(700, 500), ImGuiCond_.ImGuiCond_FirstUseEver);

    _, self.m_bOpen = ImGui.Begin(self.m_szWndName, self.m_bOpen);
    self:draw();
    ImGui.End();
end

function Ui:transport2Player()
    if PLATFORM_PC then 
        LOG_I("[ChangeClothUi:transport2Player] ", self.m_dt.m_actor)
        
        if not self.m_dt.m_actor then
            return
        end

        local bRetCode = false;
        local tbPlayerPos = { fX = 0, fY = 0, fZ = 0 };
        local tbPlayerRot = { fYaw = 0, fPitch = 0, fRoll = 0 };
        local localPlayer = g_ActorManager:GetLocalPlayer();
        bRetCode, tbPlayerPos.fX, tbPlayerPos.fY, tbPlayerPos.fZ = localPlayer:GetWorldPosition();
        if not bRetCode then
            return
        end

        bRetCode, tbPlayerRot.fPitch, tbPlayerRot.fYaw, tbPlayerRot.fRoll = localPlayer:GetWorldRotation();
        if not bRetCode then
            return
        end

        tbPlayerPos.fY = tbPlayerPos.fY + 150
        LOG_I("[ChangeClothUi:transport2Player] POSITION: ", tbPlayerPos.fX, tbPlayerPos.fY, tbPlayerPos.fZ)
        --LOG_I("[ChangeClothUi:transport2Player] ROTATION: ", tbPlayerRot.fYaw, tbPlayerRot.fPitch, tbPlayerRot.fRoll)
        self.m_dt.m_actor:SetWorldPosition(tbPlayerPos.fX, tbPlayerPos.fY, tbPlayerPos.fZ);
        --self.m_dt.m_actor:SetWorldRotation(tbPlayerRot.fYaw, tbPlayerRot.fPitch, tbPlayerRot.fRoll);
    else
        self.m_curRole = nil
        if self.m_selectCharIdx > 0 then
            LOG_I(util.u2a(self.m_tbCharList[self.m_selectCharIdx]))
            local localPlayer = g_ActorManager:GetLocalPlayer();
            if localPlayer then
                local roleType = localPlayer:GetRoleType()
                if roleType ~= g_tRoleType[self.m_selectCharIdx] then
                    return 
                end
                self.m_curRole = localPlayer
            end
        end

    end
end

function Ui:createActor(szMeshPath)
    if self.m_dt.m_actor ~= nil and self.m_dt.m_actor:IsValid() then
        return
    end
    self.m_dt.m_actor = nil;

    self.m_dt.m_actor = g_ActorManager:CreateSkeletalMeshActor(szMeshPath);
    self:transport2Player();
end

function Ui:setSelectedCharIdx(charIdx)
    if PLATFORM_PC then 
        LOG_I("[Ui:setSelectedCharIdx] ", charIdx);
        if self.m_selectCharIdx == charIdx then
            return
        end

        self.m_selectCharIdx = charIdx;
        self:clearPartModel();

        local tbDefault = Cfg:GetCharDefaultParts(self.m_selectCharIdx, self.m_bEnableHD);
        if tbDefault.DefaultModel == nil then
            return
        end
        LOG_I("[Ui:setSelectedCharIdx] ", charIdx, tbDefault.DefaultModel, #tbDefault.DefaultParts);
        self:createActor(tbDefault.DefaultModel);
        if self.m_dt.m_actor == nil then
            return;
        end

        for _, tbPartItem in ipairs(tbDefault.DefaultParts) do
            local nPartIdx = tbPartItem.nPartIdx;
            local szModelPath = tbPartItem.szModelPath;
            local szBindSocket = Cfg:GetPartBindSocket(nPartIdx);
            LOG_I("[ChangeClothUi:setSelectedCharIdx] DefaultPart", nPartIdx, szModelPath, szBindSocket)
            self.m_dt.m_actor:BindActorPart(nPartIdx, szModelPath, szBindSocket);
        end
    else
        LOG_I("[Ui:setSelectedCharIdx] ", charIdx);
        if self.m_selectCharIdx == charIdx then
            return
        end

        self.m_selectCharIdx = charIdx;
        local tbDefault = Cfg:GetCharDefaultParts(self.m_selectCharIdx, self.m_bEnableHD);
        if tbDefault.DefaultModel == nil then
            return
        end
        LOG_I("[Ui:setSelectedCharIdx] ", charIdx, tbDefault.DefaultModel, #tbDefault.DefaultParts);

        self:transport2Player();
    end
end

function Ui:clearPartModel()
    if PLATFORM_PC then
        if not self.m_dt.m_actor then
            return;
        end
        self.m_dt.m_actor:ClearActorPart();
    else
        if not self.m_curRole then
            return;
        end
        self.m_curRole:ClearActorPart();
    end

end

function Ui:getSelectedCharPartModel()
    if self.m_selectCharIdx <= 0 or self.m_selectPartIdx <= 0 then
        return "";
    end

    if self.m_tbSelectedCharPartModel[self.m_selectCharIdx] == nil then
        self.m_tbSelectedCharPartModel[self.m_selectCharIdx] = {};
    end
    local szModel = self.m_tbSelectedCharPartModel[self.m_selectCharIdx][self.m_selectPartIdx];
    return szModel or ""
end

function Ui:unBindPartModel()
    if PLATFORM_PC then
        if not self.m_dt.m_actor then
            return;
        end
        self.m_dt.m_actor:UnBindActorPart(self.m_selectPartIdx);
    else
        if not self.m_curRole then
            return;
        end
        self.m_curRole:UnBindActorPart(self.m_selectPartIdx);
    end

end

function Ui:setSelectedCharPartModel(partIdx, szModel)
    if self.m_selectCharIdx <= 0 or partIdx <= 0 then
        return;
    end

    if self.m_tbSelectedCharPartModel[self.m_selectCharIdx] == nil then
        self.m_tbSelectedCharPartModel[self.m_selectCharIdx] = {};
    end
    self.m_tbSelectedCharPartModel[self.m_selectCharIdx][partIdx] = szModel;

    if PLATFORM_PC then
        if self.m_dt.m_actor then
            local szModelPath = szModel;
            local szBindSocket = Cfg:GetPartBindSocket(partIdx);
            LOG_I("[ChangeClothUi setSelectedCharPartModel]", self.m_selectCharIdx, partIdx, szModelPath, szBindSocket);
            self.m_dt.m_actor:BindActorPart(partIdx, szModelPath, szBindSocket);
        end
    else
        if self.m_curRole then
            local szModelPath = szModel;
            local szBindSocket = Cfg:GetPartBindSocket(partIdx);
            LOG_I("[ChangeClothUi setSelectedCharPartModel]", self.m_selectCharIdx, partIdx, szModelPath, szBindSocket);
            self.m_curRole:BindActorPart(partIdx, szModelPath, szBindSocket);
        end
    end
end

function Ui:loadSuit()
    local szModel = self:getSelectedCharPartModel()
    LOG_I("loadSuit 1", szModel)
    if szModel == "" then
        return;
    end

    local szSuitKey = Cfg:GetSuitKeyOfModelFile(szModel);
    LOG_I("loadSuit 2", szSuitKey)
    if szSuitKey == nil or string.len(szSuitKey) <= 0 then
        return;
    end

    local partList = Cfg:GetSuitPartList(self.m_selectCharIdx, szSuitKey, self.m_bEnableSD, self.m_bEnableHD);
    LOG_I("loadSuit 3", partList, #partList)
    self:clearPartModel();
    for partIdx, partModel in pairs(partList) do
        self:setSelectedCharPartModel(partIdx, partModel);
    end
end

function Ui:draw()
    local charList = self.m_tbCharList;
    if #charList <= 0 then
        return
    end
    local partList = self.m_tbPartList;
    if #partList <= 0 then
        return
    end
    if self.m_selectCharIdx <=0 or self.m_selectCharIdx > #charList then
        self:setSelectedCharIdx(1);
    end
    if self.m_selectPartIdx <=0 or self.m_selectPartIdx > #partList then
        self.m_selectPartIdx = 1;
    end

    ------ left ------
    ImGui.BeginChild("left pane", ImVec2(500, 0), true);
    if ImGui.BeginCombo(self.m_szCharComboName, charList[self.m_selectCharIdx], 0) then
        for idx, char in ipairs(charList) do
            local bSelected = idx == self.m_selectCharIdx;
            if ImGui.Selectable(char, bSelected) then
                self:setSelectedCharIdx(idx);
            end
            if bSelected then
                ImGui.SetItemDefaultFocus();
            end
        end
        ImGui.EndCombo();
    end
    if ImGui.BeginCombo(self.m_szPartComboName, partList[self.m_selectPartIdx], 0) then
        for idx, partName in ipairs(partList) do
            local bSelected = idx == self.m_selectPartIdx;
            if ImGui.Selectable(partName, bSelected) then
                self.m_selectPartIdx = idx;
            end
            if bSelected then
                ImGui.SetItemDefaultFocus();
            end
        end
        ImGui.EndCombo();
    end

    if ImGui.Button(self.m_szRmvPartBtnName) then
        self:unBindPartModel();
    end
    ImGui.SameLine();
    if ImGui.Button(self.m_szClearPartBtnName) then
        self:clearPartModel();
    end

    _, self.m_bEnableSD = ImGui.Checkbox(self.m_szSModelChkBoxName, self.m_bEnableSD);
    --ImGui.SameLine();
    _, self.m_bEnableHD = ImGui.Checkbox(self.m_szHModelChkBoxName, self.m_bEnableHD);
    if ImGui.Button(self.m_szLoadSuitBtnName) then
        self:loadSuit();
    end
    if g_App:IsDebug() then
        if ImGui.Button("test serialize") then
            self:testSerialize();
        end
    end
    ImGui.EndChild();

    ImGui.SameLine();

    ------ right ------
    ImGui.BeginChild("right pane", ImVec2(450, 0), true);
    if self.m_imguiModelFilter ~= nil then
        self.m_imguiModelFilter:Draw();
    end
    if self.m_bEnableSD or self.m_bEnableHD then
        local tbCharPartModelList = Cfg:GetModelListOfSpecCharPart(self.m_selectCharIdx, self.m_selectPartIdx);
        self:drawPartModelList(tbCharPartModelList);
    end
    ImGui.EndChild();
end

function Ui:testSerialize()
    if not self.m_dt.m_actor then
        return;
    end
    local strJson = g_ActorManager:SaveActorToJson(self.m_dt.m_actor);
    print("Ui:testSerialize, ActorJson:", string.len(strJson));

    local tbActors = g_ActorManager:LoadActorFromJson(strJson);
    print("Ui:testSerialize, JsonActors:", #tbActors)
    for _, lActor in ipairs(tbActors) do
        print("Ui:testSerialize, lActor", lActor.SetMeshRes)
    end
end

function Ui:drawPartModelList(tbCharPartModelList)
    local szSelectedModel = self:getSelectedCharPartModel();
    for idx, tbModelItem in pairs(tbCharPartModelList) do
        local szLowerModelFile = string.lower(tbModelItem.szPath);
        local bHDModel = string.find(szLowerModelFile, "hd") ~= nil;
        local bFilter = false;
        if not self.m_bEnableSD and not bHDModel then
            bFilter = true;
        end
        if not self.m_bEnableHD and bHDModel then
            bFilter = true;
        end

        if not bFilter and self.m_imguiModelFilter ~= nil then
            bFilter = self.m_imguiModelFilter:PassFilter(tbModelItem.szPath)
        end

        local bSelected = szSelectedModel == tbModelItem.szPath;
        if not bFilter and ImGui.Selectable(tbModelItem.szUtf8Name, bSelected) then
            self:setSelectedCharPartModel(self.m_selectPartIdx, tbModelItem.szPath);
        end
    end
end

UiInst = Ui:new();
