%%%-------------------------------------------------------------------
%%% @author liushl
%%% @doc
%%%     狂战领域阶段切换
%%% rr("../include/*.hrl").
%%% sys:get_state(madness_land).
%%% scene_mgr:get_scene_pool_ids(7800). utime:unixtime_to_localtime(1600314419).
%%% erlang:process_info(whereis(madness_land),dictionary).
%%%
%%% @end
%%%-------------------------------------------------------------------
-module(madness_land_stage).
-author("liushl").

-include("madness_land.hrl").
-include("common.hrl").
-include("def_fun.hrl").
-include("def_module.hrl").
-include("figure.hrl").
%% API
-export([
    stage_begin/1,                  %% 开始玩法
    stage_switch/1,                 %% 阶段切换
    set_timer_cycle_add_score/1,    %% 开启循环加积分定时器
    set_timer_refresh_rank/0        %% 开启排行榜刷新定时器
]).

%% 本服。活动开始，进入第一阶段-进入第一轮
stage_begin(#madness_land{cls_type = ?NODE_GAME} = State) ->
    NextStage = ?MADNESS_LAND_STAGE_ROUND_1,
    StageTime = get_sage_time(NextStage),
    lib_chat:send_TV({all}, ?MOD_MADNESS_LAND, 1, []),
    Now = utime:unixtime(),
    EndTime = Now + StageTime,
    Round = 1,
    #madness_land{
        cls_type              = ?NODE_GAME
        , stage               = NextStage
        , round               = Round
        , end_time            = EndTime
        , ref_stage_switch    = set_timer_stage_switch(State#madness_land.ref_stage_switch, NextStage, StageTime)
        , ref_cycle_add_score = set_timer_cycle_add_score(NextStage)
        , ref_refresh_rank    = set_timer_refresh_rank()
        , ref_mon_born        = set_timer_mon_born(Round)
        , local_data          = #madness_land_act{}
        , check_host_pid      = offline_hosting_madness_land:check_hosting()
    };
%% 跨服。活动开始，无需处理
stage_begin(#madness_land{cls_type = ?NODE_CENTER} = State) ->
    NextStage = ?MADNESS_LAND_STAGE_ROUND_1,
    StageTime = get_sage_time(NextStage),
    #madness_land{
        cls_type              = ?NODE_CENTER
        , stage               = NextStage
        , round               = 1
        , end_time            = utime:unixtime() + StageTime
        , ref_stage_switch    = set_timer_stage_switch(State#madness_land.ref_stage_switch, NextStage, StageTime)
    }.

%% 本服。第一轮BOSS死亡, 啥都不干，光杀死BOSS
stage_switch(#madness_land{stage = ?MADNESS_LAND_STAGE_ROUND_1, cls_type = ?NODE_GAME, check_host_pid = Pid} = State)->
    madness_land_act:clean_round_boss(State#madness_land.round, State#madness_land.cls_type),
    %% 以防万一，停止加载托管进程
    misc:is_process_alive(Pid) andalso erlang:exit(Pid, kill),
    NextStage = ?MADNESS_LAND_STAGE_RESET,
    StageTime = get_sage_time(NextStage),
    %% 前端显示倒计时15进入下一轮
    broadcast_stage_switch(NextStage, State#madness_land.end_time, ?MADNESS_LAND_SCENE_ROUND_1),
    %% 传闻BOSS死亡
    lib_chat:send_TV({scene, ?MADNESS_LAND_SCENE_ROUND_1}, ?MOD_MADNESS_LAND, 3, []),
    %% 停止循环加分
    util:cancel_timer(State#madness_land.ref_cycle_add_score),
    State#madness_land{
        stage = NextStage
        , ref_stage_switch     = set_timer_stage_switch(State#madness_land.ref_stage_switch, NextStage, StageTime)
        , check_host_pid       = undefined
    };

%% 本服。第一轮结束，进入第二轮
stage_switch(#madness_land{stage = ?MADNESS_LAND_STAGE_RESET, cls_type = ?NODE_GAME} = State) ->
    Now = utime:unixtime(),
    %% 停止本轮
    stop_round(State),
    %% 先强制刷新一遍榜单：第一轮的
    ActData = State#madness_land.local_data,
    {State1, RoleRank, GuildRank} =
        madness_land_act:refresh_rank(State, ActData#madness_land_act{refresh_flag = true}),
    %% 结算
    madness_land_act:settlement_local(
        State1#madness_land.round,
        RoleRank,
        GuildRank,
        State1,
        State1#madness_land.local_data,
        Now
    ),
    NextStage = ?MADNESS_LAND_STAGE_ROUND_2,
    StageTime = get_sage_time(NextStage),
    %% 确定第二轮开始位置
    SecondType = case State#madness_land.round_2_type of
        ?NODE_CENTER ->
            madness_land_api:get_act_type();
        _ ->
            ?NODE_GAME
    end,
    %% 将所有玩家踢至第二轮场景
    madness_land_act:pull_role_into_round2(SecondType),
    %% TA上报
    madness_land_api:ta_data_upload(1, State1#madness_land.local_data#madness_land_act.role_grade),
    Round = 2,
    EndTime = Now + StageTime,
    State#madness_land{
        cls_type              = ?NODE_GAME
        , stage               = NextStage
        , end_time            = EndTime
        , round               = Round
        , round_2_type        = SecondType
        , ref_stage_switch    = set_timer_stage_switch(State#madness_land.ref_stage_switch, NextStage, StageTime)
        , ref_cycle_add_score = ?IF(SecondType =:= ?NODE_GAME, set_timer_cycle_add_score(NextStage), undefined)   %%  循环加分定时器
        , ref_mon_born        = ?IF(SecondType =:= ?NODE_GAME, set_timer_mon_born(Round), undefined)
        , ref_refresh_rank    = ?IF(SecondType =:= ?NODE_GAME, set_timer_refresh_rank(), undefined)
        , role_rank           = ?IF(SecondType =:= ?NODE_GAME, #{}, State1#madness_land.role_rank)
        , guild_rank          = ?IF(SecondType =:= ?NODE_GAME, #{}, State1#madness_land.guild_rank)
        , local_data          = ?IF(SecondType =:= ?NODE_GAME, #madness_land_act{}, undefined)
        %% 记录第一轮成绩
        , round_1_role_grade   = State1#madness_land.local_data#madness_land_act.role_grade
        , round_1_guild_grade  = State1#madness_land.local_data#madness_land_act.guild_grade
        , round_1_first_attack = State1#madness_land.local_data#madness_land_act.boss_first_attack_role
    };

%% 本服。第二轮结算:只杀死BOSS，啥都不干
stage_switch(#madness_land{stage = ?MADNESS_LAND_STAGE_ROUND_2, cls_type = ?NODE_GAME} = State) ->
    NextStage = ?MADNESS_LAND_STAGE_END,
    StageTime = get_sage_time(NextStage),
    case State#madness_land.round_2_type of
        ?NODE_CENTER ->
            %% 第二轮活动在跨服，不需要处理
            ok;
        ?NODE_GAME  ->
            %% 广播前端15s倒计时结束活动
            %% 停止循环加分
            util:cancel_timer(State#madness_land.ref_cycle_add_score),
            madness_land_act:clean_round_boss(State#madness_land.round, ?NODE_GAME),
            broadcast_stage_switch(NextStage, State#madness_land.end_time, ?MADNESS_LAND_SCENE_ROUND_2_NODE)
    end,
    State#madness_land{
        stage = NextStage
        , ref_stage_switch     = set_timer_stage_switch(State#madness_land.ref_stage_switch, NextStage, StageTime)
    };

%% 跨服。 跨服中心第一轮没活动，所以无需处理
stage_switch(#madness_land{stage = ?MADNESS_LAND_STAGE_ROUND_1, cls_type = ?NODE_CENTER} = State) ->
    NextStage = ?MADNESS_LAND_STAGE_RESET,
    StageTime = get_sage_time(NextStage),
    State#madness_land{
        stage = NextStage
        , ref_stage_switch  = set_timer_stage_switch(State#madness_land.ref_stage_switch, NextStage, StageTime)
    };

%% 跨服。 第一轮结束，进入第二轮, 跨服活动开启
stage_switch(#madness_land{stage = ?MADNESS_LAND_STAGE_RESET, cls_type = ?NODE_CENTER} = State) ->
    NextStage = ?MADNESS_LAND_STAGE_ROUND_2,
    StageTime = get_sage_time(NextStage),
    Round = 2,
    Now = utime:unixtime(),
    EndTime = Now + StageTime,
    State#madness_land{
        stage               = NextStage
        , round               = Round
        , round_2_type        = ?NODE_CENTER
        , end_time            = EndTime
        , ref_stage_switch    = set_timer_stage_switch(State#madness_land.ref_stage_switch, NextStage, StageTime)
        , ref_refresh_rank    = set_timer_refresh_rank()
        , ref_cycle_add_score = set_timer_cycle_add_score(NextStage)   %%  循环加分定时器
        , ref_mon_born        = set_timer_mon_born(Round)
    };

%% 跨服。 第二轮 BOSS狂暴
stage_switch(#madness_land{stage = ?MADNESS_LAND_STAGE_ROUND_2, cls_type = ?NODE_CENTER} = State) ->
    %% 停止循环加分
    util:cancel_timer(State#madness_land.ref_cycle_add_score),
    NextStage = ?MADNESS_LAND_STAGE_END,
    StageTime = get_sage_time(NextStage),
    madness_land_act:clean_round_boss(State#madness_land.round, State#madness_land.cls_type),
    broadcast_stage_switch(NextStage, State#madness_land.end_time, ?MADNESS_LAND_SCENE_ROUND_2_CENTER),
    State#madness_land{
        stage = NextStage
        , ref_stage_switch      = set_timer_stage_switch(State#madness_land.ref_stage_switch, NextStage, StageTime)
    };

%% 本服：活动结束
stage_switch(#madness_land{stage = ?MADNESS_LAND_STAGE_END, cls_type = ?NODE_GAME} = State) ->
    #madness_land{
        round_2_type = Round2Type,
        round = Round
    } = State,
    case Round2Type of
        ?NODE_CENTER ->
            %% 第二轮活动在跨服，不需要结算
            State1 = State;
        ?NODE_GAME  ->
            Now = utime:unixtime(),
            %% 同本服第一轮结束
            stop_round(State),
            %% 先强制刷新一遍榜单
            ActData = State#madness_land.local_data,
            {State1, RoleRank, GuildRank} = madness_land_act:refresh_rank(State, ActData#madness_land_act{refresh_flag = true}),
            %% 结算
            madness_land_act:settlement_local(
                Round,
                RoleRank,
                GuildRank,
                State1,
                State1#madness_land.local_data,
                Now
            )
    end,
    madness_land_act:close_act(?NODE_GAME),
    #madness_land{
        role_rank = NewRoleRank,
        guild_rank = NewGuildRank
    } = State1,
    %% 保存榜单
    LocalRoleRank = maps:get(0, NewRoleRank, []),
    RoleRankData =
        [
            {Rank, RoleId, Score}
            || #madness_land_role{
                    role_id         = RoleId
                    , score         = Score
                    , rank          = Rank
                } <- LocalRoleRank
        ],
    spawn(madness_land_act, save_rank_data, [local_role, RoleRankData]),
    GuildRankData =
        [
            {Rank, GuildName, GuildFlag, Score}
            || #madness_land_guild{
                    guild_name     = GuildName
                    , score          = Score
                    , rank           = Rank
                    , guild_flag     = GuildFlag
                } <- maps:get(0, NewGuildRank, [])
        ],
    %% 第二轮如果是本服的话，发送本服榜首传闻
    Round2Type =:= ?NODE_GAME andalso
        case lists:keyfind(1, 1, GuildRankData) of
            {_, TopGuild, _} ->
                lib_chat:send_TV({all}, ?MOD_MADNESS_LAND, 21, [TopGuild]),
                case lists:keyfind(1, #madness_land_role.rank, LocalRoleRank) of
                    #madness_land_role{role_id = TopId, picture = #rec_picture{name = TopName}} ->
                        lib_chat:send_TV({all}, ?MOD_MADNESS_LAND, 22, [TopName, TopId]);
                    _ ->
                        ok
                end;
            _ ->
                ok
        end,
    spawn(madness_land_act, save_rank_data, [local_guild, GuildRankData]),
    %% 一段时间后，等结算完，清理第一轮成绩
    erlang:send_after(60000, self(), clean_data),
    State#madness_land{
        cls_type        = ?NODE_GAME,
        stage           = ?MADNESS_LAND_STAGE_IDLE,
        end_time        = 0,
        round           = 0,
        role_rank       = NewRoleRank,
        guild_rank      = NewGuildRank
    };
%% 跨服：活动结束
stage_switch(#madness_land{stage = ?MADNESS_LAND_STAGE_END, cls_type = ?NODE_CENTER} = State) ->
    stop_round(State),
    %% 结算
    State2 = maps:fold(
        fun(ZoneId, ZoneData, Temp) ->
            %% 强制刷新一次榜单
            {State1, RoleRank, GuildRank} =
                madness_land_act:refresh_rank(Temp, ZoneData#madness_land_act{refresh_flag = true}),
            TopServer =
            case GuildRank of
                [#madness_land_guild{server_num = TopGuildServer}|_] -> TopGuildServer;
                _ -> 0
            end,
            ZoneStage = czone:get_zone_stage(ZoneId),
            madness_land_act:settlement_center(RoleRank, GuildRank, ZoneData, TopServer, ZoneStage, utime:unixtime()),
            State1
        end, State, State#madness_land.zone_data
    ),
    madness_land_act:close_act(?NODE_CENTER),
    #madness_land{
        role_rank = NewRoleRank,
        guild_rank = NewGuildRank
    } = State2,
    RoleRankData = maps:fold(
        fun(ZoneId, Value, Temp) ->
            %% 广播第一
            madness_land_act:broadcast_top_role(ZoneId, Value),
            [
                {ZoneId, Rank, RoleId, Name, Sex, Vip, SupVip, ServerNum, Score, Photo, PhotoDress, Career, Turn}
                || #madness_land_role{
                        role_id         = RoleId
                        , server_num    = ServerNum
                        , picture       = #rec_picture{name = Name, sex = Sex, vip = Vip, sup_vip = SupVip,
                    profile_photo_id = Photo, picture_frame = PhotoDress, turn = Turn, career = Career}
                        , score         = Score
                        , rank          = Rank
                    } <- Value
            ] ++ Temp
        end, [], NewRoleRank
    ),
    spawn(madness_land_act, save_rank_data, [center_role, RoleRankData]),
    GuildRankData = maps:fold(
        fun(ZoneId, Value, Temp) ->
            %% 排名第一的服务器需要发全服邮件
            madness_land_act:send_server_reward_mail(ZoneId, Value),
            [
                {ZoneId, Rank, ServerNum, GuildName, Score, GuildFlag}
                || #madness_land_guild{
                        server_num       = ServerNum
                        , guild_name     = GuildName
                        , score          = Score
                        , rank           = Rank
                        , guild_flag     = GuildFlag
                    } <- Value
            ] ++ Temp
        end, [], NewGuildRank
    ),
    spawn(madness_land_act, save_rank_data, [center_guild, GuildRankData]),
    #madness_land{
        cls_type        = ?NODE_CENTER,
        stage           = ?MADNESS_LAND_STAGE_IDLE,
        role_rank       = NewRoleRank,
        guild_rank      = NewGuildRank
    };
stage_switch(State) -> State.

%% 阶段持续时长:最开始的开发在结束前有一个休闲时间，现在不用了，所以直接配为1
get_sage_time(Stage) ->
    case Stage of
        ?MADNESS_LAND_STAGE_ROUND_1 ->
            ?MADNESS_LAND_ROUND_1_TIME;
        ?MADNESS_LAND_STAGE_RESET ->
            ?MADNESS_LAND_ROUND_REST_TIME;
        ?MADNESS_LAND_STAGE_ROUND_2 ->
            ?MADNESS_LAND_ROUND_2_TIME;
        ?MADNESS_LAND_STAGE_END ->
            ?MADNESS_LAND_ROUND_REST_TIME
    end.

%% 开启循环加积分定时器
%% 游戏服开启定时器:第一轮或者第二轮也在本服
set_timer_cycle_add_score(Stage) ->
    erlang:send_after(?MADNESS_LAND_CYCLE_SCORE_TIME*1000, self(), {cycle_add_score, Stage}).

%% 开启定时器出生小怪
set_timer_mon_born(1) ->
    erlang:send_after(?MADNESS_LAND_ROUND_1_MON_BORN*1000, self(), mon_born);
set_timer_mon_born(2) ->
    erlang:send_after(?MADNESS_LAND_ROUND_2_MON_BORN*1000, self(), mon_born).

%% 开启阶段切换定时器
%% Stage当前阶段
%% 定时进入下一阶段
set_timer_stage_switch(OldRef, Stage, Time) ->
    util:cancel_timer(OldRef),
    %% 轮次开始时，提前进入15秒杀死BOSS，进入下一阶段
    DiffTime =
    case Stage of
        ?MADNESS_LAND_STAGE_ROUND_1 ->
            Time - get_sage_time(?MADNESS_LAND_STAGE_RESET);
        ?MADNESS_LAND_STAGE_ROUND_2 ->
            Time - get_sage_time(?MADNESS_LAND_STAGE_RESET);
        _ ->
            Time
    end,
    erlang:send_after(DiffTime*1000, self(), stage_switch).

%% 开启排行榜刷新定时器
set_timer_refresh_rank() ->
    erlang:send_after(3*1000, self(), refresh_rank).

stop_round(State) ->
    %% 停止循环加分
    util:cancel_timer(State#madness_land.ref_cycle_add_score),
    %% 停止榜单刷新
    util:cancel_timer(State#madness_land.ref_refresh_rank),
    %% 停止刷小怪
    util:cancel_timer(State#madness_land.ref_mon_born).

broadcast_stage_switch(Stage, EndTime, Scene) ->
    {ok, Bin} = pt_415:write(41500, [Stage, EndTime]),
    [lib_server_send:send_to_scene(Scene, PoolId, Bin) || PoolId <- scene_mgr:get_scene_pool_ids(Scene)].
    
    
