---
--- Generated manually.
--- Created by liaogaocan.
--- DateTime: 2020-6-29 11:28:29
---

local LGameStateManager = ImportScript("ugc_common/script/core/game_state/game_state_manager.lua")
local LIniFile = ImportScript("ugc_common/script/core/file/inifile.lua").LIniFile

local LPCGameStateManager = LPCGameStateManager or class("LPCGameStateManager");

function LPCGameStateManager:ctor()
    self.m_szLoginMapPath = "UGCSource\\maps\\1024\\1024.jsonmap";

    self.m_szMapPath = nil;
    self.m_szActorPath = nil;
    self.m_tbInitPos = {100, 1000, 100};

    self.m_bSceneReady = false;
    self.m_fSceneLoadingProgress = 0;
    self.m_bInGame = false;
end

function LPCGameStateManager:dtor()
    --
end

function LPCGameStateManager:Init()
    LOG_I("[LPCGameStateManager:Init]");
    g_EventDispatcherManager:AddEventListener("game_state", "start", self.onGameStart, self);
    g_EventDispatcherManager:AddEventListener("game_state", "end", self.onGameEnd, self);
    g_EventDispatcherManager:AddEventListener("game_state", "login", self.onLogin, self);
    
    g_HBUIEventDispatcher:AddEventListener(HBUIEvent.UI2S_RefreshSceneLoadingProgress, self.onResponseHBUIProgress, self);
    g_HBUIEventDispatcher:AddEventListener(HBUIEvent.UI2S_ReturnToStartGame, self.onHBUIClickExit, self);
    g_HBUIEventDispatcher:AddEventListener(HBUIEvent.UI2S_UpdateMapInfo, self.onHBUIUpdateMapInfo, self);
    g_HBUIEventDispatcher:AddEventListener(HBUIEvent.UI2S_UpdateMapLocation, self.onHBUIUpdateMapLocation, self);
    g_HBUIEventDispatcher:AddEventListener(HBUIEvent.UI2S_RelocatePlayer, self.onHBUIRelocatePlayer, self);
end

function LPCGameStateManager:UnInit()
    LOG_I("[LPCGameStateManager:UnInit]");

    g_HBUIEventDispatcher:RemoveEventListener(HBUIEvent.UI2S_RefreshSceneLoadingProgress, self.onResponseHBUIProgress, self);
    g_HBUIEventDispatcher:RemoveEventListener(HBUIEvent.UI2S_ReturnToStartGame, self.onHBUIClickExit, self);
    g_HBUIEventDispatcher:RemoveEventListener(HBUIEvent.UI2S_UpdateMapInfo, self.onHBUIUpdateMapInfo, self);
    g_HBUIEventDispatcher:RemoveEventListener(HBUIEvent.UI2S_UpdateMapLocation, self.onHBUIUpdateMapLocation, self);
    g_HBUIEventDispatcher:RemoveEventListener(HBUIEvent.UI2S_RelocatePlayer, self.onHBUIRelocatePlayer, self);

    g_EventDispatcherManager:RemoveEventListener("game_state", "start", self.onGameStart, self);
    g_EventDispatcherManager:RemoveEventListener("game_state", "end", self.onGameEnd, self);
    g_EventDispatcherManager:RemoveEventListener("game_state", "login", self.onLogin, self);
end

function LPCGameStateManager:GameTick()
    --
end

function LPCGameStateManager:onGameStart()
    local bRetCode = g_SceneManager:BrowseMapByResPath(self.m_szLoginMapPath, "");
    LOG_I("[LPCGameStateManager:onGameStart] browse map ", bRetCode);
    if not bRetCode then
       return;
    end

    g_CameraController:SetFovAngleY(45.0);
    g_CameraController:SetAspectRatio(16.0/9.0);
    g_CameraController:SetNearPlane(50.0);
    g_CameraController:SetFarPlane(100000.0);
end

function LPCGameStateManager:onGameEnd()
    local bRetCode =  g_SceneManager:DestroyCurMap();
    LOG_I("[LPCGameStateManager:onGameEnd]", bRetCode);
end

function LPCGameStateManager:onLogin(data)
    if nil == data then
        return;
    end

    local loginData = cjson.decode(data);
    self.m_szMapPath = loginData.mappath;
    self.m_szActorPath = loginData.actorpath;
    if nil == self.m_szMapPath or nil == self.m_szActorPath then
        LOG_E("[LPCGameStateManager:onLogin]", "mapPath =", self.m_szMapPath, "actorPath =", self.m_szActorPath);
        return;
    end

    local szKMSCPath = "";

    local breadcrumbs = string.split(self.m_szMapPath, "%.");
    local postfix = table.remove(breadcrumbs);
    if "jsonmap" == postfix then
        local bOK, tbPos = util.ReadMainCameraPositionFromJsonmap(self.m_szMapPath);
        if true == bOK then
            self.m_tbInitPos = tbPos;
        end
    elseif "kms" == postfix then
        local bOK, tbInfo = util.ExtractEssentialsFromKMS(self.m_szMapPath);
        if true == bOK then
            self.m_tbInitPos = tbInfo.CameraPos;
            szKMSCPath = self.m_szMapPath.."c";
            self.m_szMapPath = tbInfo.MapPath;
        end
    end

    g_EventDispatcherManager:AddEventListener("scene", "onProgress", self.onSceneLoadingProgress, self);
    g_EventDispatcherManager:AddEventListener("scene", "created", self.onSceneCreated, self);
    g_EventDispatcherManager:AddEventListener("scene", "ready", self.onSceneReady, self);
    
    local bRetCode = g_SceneManager:BrowseMapByResPath(self.m_szMapPath, szKMSCPath);
    LOG_I("[LPCGameStateManager:onLogin] browse map ", bRetCode);
end

function LPCGameStateManager:onSceneLoadingProgress(data)
    local progressInfo = cjson.decode(data);

    local fJsonmapPart = 0.4;
    local fKMSCPart = 0.5;
    local fSplinePart = 0.1;

    local fProgress = fJsonmapPart;

    if 1 == progressInfo.bNeedToLoadPlot then
        if 0 ~= progressInfo.nPlotObjTotalNum then
            fProgress = fProgress + fKMSCPart * progressInfo.nPlotObjLoadedNum / progressInfo.nPlotObjTotalNum;
        else
            fProgress = fProgress + fKMSCPart;
        end
    else
        fProgress = fProgress + fKMSCPart;
    end

    if 1 == progressInfo.bSplinePhysicsReady then
        fProgress = fProgress + fSplinePart;
    end

    self.m_fSceneLoadingProgress = fProgress;
end

function LPCGameStateManager:onResponseHBUIProgress()
    local hbuiEvtData = {
        progress = self.m_fSceneLoadingProgress
    };

    if true == self.m_bSceneReady then
        hbuiEvtData.progress = 1.0;
    end

    KLHbui.TriggerEvent(HBUIEvent.S2UI_RefreshSceneLoadingProgress, cjson.encode(hbuiEvtData));

    if true == self.m_bSceneReady then
        local hbuiEvtData = {};
        hbuiEvtData.isLogicScene = not self.m_bInGame;
        KLHbui.TriggerEvent(HBUIEvent.S2UI_OnSceneLoaded, cjson.encode(hbuiEvtData));
    end
end

function LPCGameStateManager:onHBUIClickExit()
    g_EventDispatcherManager:AddEventListener("scene", "onProgress", self.onSceneLoadingProgress, self);
    g_EventDispatcherManager:AddEventListener("scene", "created", self.onSceneCreated, self);
    g_EventDispatcherManager:AddEventListener("scene", "ready", self.onSceneReady, self);

    KLHbui.TriggerEvent(HBUIEvent.S2UI_ReturnToStartGame, "{}");

    local bRetCode = g_SceneManager:BrowseMapByResPath(self.m_szLoginMapPath, "");
    LOG_I("[LPCGameStateManager:onHBUIClickExit] browse map ", bRetCode);
end

function LPCGameStateManager:onSceneCreated()
    self.m_bSceneReady = false;
    self.m_fSceneLoadingProgress = 0;
end

function LPCGameStateManager:onSceneReady()
    if false == self.m_bInGame then
        local player = g_ActorManager:CreateLocalPlayer();
        LOG_I("[LPCGameStateManager:onLogin] player ", player, player:GetCollisionType(), player:IsSimulatePhysics());
        local tbInitPos = self.m_tbInitPos;
        print("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~init pos = ", tbInitPos[1], tbInitPos[2]+500, tbInitPos[3]);
        player:SetWorldPosition(tbInitPos[1], tbInitPos[2]+500, tbInitPos[3]);
        player:SetMeshRes("UGCSource\\player\\"..self.m_szActorPath);

        g_DataStorage:Load();

        -- 获取体型：F1, F2, M1, M2
        local fnGetActorJsonGeometry = function(szActorPath)
            -- get actor type
            local data = LIniFile.load(szActorPath);
            local szModel = data.ROOT.DependModel or "";
            local szType = string.match(szModel, ".*\\(%a+%d+)_-[%a%d]-.mdl");
            szType = string.upper(szType or "");
            LOG_I("Actor Type: ", szType);

            -- get geometry
            local ModelGeometrySet = {
                F1 = [[
                    {
                        "Type" : "Capsule",
                        "HalfHeight" : 40.0,
                        "Radius" : 20.0 
                    }
                ]],
                F2 = [[
                    {
                        "Type" : "Capsule",
                        "HalfHeight" : 55.0,
                        "Radius" : 25.0 
                    }
                ]],
                M1 = [[
                    {
                        "Type" : "Capsule",
                        "HalfHeight" : 40.0,
                        "Radius" : 20.0 
                    }
                ]],
                M2 = [[
                    {
                        "Type" : "Capsule",
                        "HalfHeight" : 65.0,
                        "Radius" : 25.0 
                    }
                ]],
            }

            local szJsonGeometry = ModelGeometrySet[szType or "F1"];
            LOG_I("Json Geometry: ", szJsonGeometry);
            return szJsonGeometry;
        end
        
        local szJsonGeometry = fnGetActorJsonGeometry("UGCSource\\player\\"..self.m_szActorPath);

        player:SetCollisionGeometry(szJsonGeometry);
        player:SetCollisionType(Core.QueryAndPhysics);
        player:SetMaxStepHeight(25.0);
        
        --g_NetWorking:Connect(g_NetWorking.SERVER_AUTH, "127.0.0.1", 12000);
        --g_NetWorking:LoginAuth("testaaa", "123456");

        self.m_bInGame = true;
    else
        self.m_bInGame = false;
    end

    g_EventDispatcherManager:RemoveEventListener("scene", "onProgress", self.onSceneLoadingProgress, self);
    g_EventDispatcherManager:RemoveEventListener("scene", "created", self.onSceneCreated, self);
    g_EventDispatcherManager:RemoveEventListener("scene", "ready", self.onSceneReady, self);

    g_EventDispatcherManager:AddEventListener("scene", "destroy", self.onSceneDestroy, self);

    self.m_bSceneReady = true;
end

function LPCGameStateManager:onSceneDestroy()
    if true == self.m_bInGame then
        local player = g_ActorManager:GetLocalPlayer();
        if nil ~= player then
            g_ActorManager:DestroyActor(player);
        end

        g_NetWorking:onSceneDestroy();
    end

    g_EventDispatcherManager:RemoveEventListener("scene", "destroy", self.onSceneDestroy, self);
end

function LPCGameStateManager:onHBUIUpdateMapInfo(data)
    local nColumns = KLGameWorld.GetSimWorldZoneColumns();
    local nZoneSize = KLGameWorld.GetSimWorldZoneSize();
    local nOriginX = KLGameWorld.GetSimWorldOriginX();
    local nOriginY = KLGameWorld.GetSimWorldOriginY();

    if 0 == nColumns or 0 == nZoneSize then
        return;
    end

    local hbuiEvtData = {};
    hbuiEvtData.path = util.a2u8(self.m_szMapPath);
    hbuiEvtData.tileColumns = nColumns;
    hbuiEvtData.offsetTileCol = nOriginX / nZoneSize;
    hbuiEvtData.offsetTileRow = nOriginY / nZoneSize;

    KLHbui.TriggerEvent(HBUIEvent.S2UI_UpdateMapInfo, cjson.encode(hbuiEvtData));
end

function LPCGameStateManager:onHBUIUpdateMapLocation(data)
    local player = g_ActorManager:GetLocalPlayer();
    if nil == player then
        return;
    end

    local _,x,y,z = player:GetWorldPosition(0,0,0);
    local _,p,yaw,r = player:GetWorldRotation(0,0,0);
    local nSceneSize = KLGameWorld.GetSimWorldSize();
    local fOriginX = KLGameWorld.GetSimWorldOriginX();
    local fOriginY = KLGameWorld.GetSimWorldOriginY();
    print(x,y,z);

    local hbuiEvtData = {};
    --小地图不考虑偏移
    hbuiEvtData.locationX = (x - fOriginX) / nSceneSize;
    hbuiEvtData.locationY = (z - fOriginY) / nSceneSize;
    hbuiEvtData.direction = yaw + 180;

    KLHbui.TriggerEvent(HBUIEvent.S2UI_UpdateMapLocation, cjson.encode(hbuiEvtData));
end

function LPCGameStateManager:onHBUIRelocatePlayer(data)
    local player = g_ActorManager:GetLocalPlayer();
    if nil == player then
        return;
    end

    while nil ~= player:GetAttachParent() do
        player = player:GetAttachParent();
    end

    local nSceneSize = KLGameWorld.GetSimWorldSize();    
    local X = data.xPercent * nSceneSize;
    local Z = data.yPercent * nSceneSize;

    --GetFloor背后所依赖的SimWorld是考虑原点偏移的，
    --小地图传过来的坐标没有考虑偏移
    --所以要在这里加上偏移还原回真实坐标
    local fOriginX = KLGameWorld.GetSimWorldOriginX();
    local fOriginY = KLGameWorld.GetSimWorldOriginY();
    X = X + fOriginX;
    Z = Z + fOriginY;
        
    -- --老是意外穿透到地下是因为高度图来不及加载，这种情况让他在20米处自由下落。
    -- --如果高度图已加载的，那就在原有基础上加10米处下落。
    -- local nHeight = KLGameWorld.GetSimWorldFloor(X, Z);
    -- if 0 == nHeight then
    --     nHeight = 2000;
    -- else
    --     nHeight = nHeight + 1000;
    -- end

    -- 传送不处理高度了，完全交给移动组件处理
    local _,_,nHeight,_ = player:GetWorldPosition(0,0,0); 

    player:SetWorldPosition(X, nHeight, Z, true);
    LOG_I(string.format("onHBUIRelocatePlayer|xp=%f zp=%f xyz=%f,%f,%f", data.xPercent, data.yPercent, X, nHeight, Z));
end

_G.g_GameStateManager = LPCGameStateManager:new();

