%%%-------------------------------------------------------------------
%%% @author liushl
%%% @doc
%%%     本服公会战-逻辑入口
%%% @end
%%%-------------------------------------------------------------------
-module(guild_war_api).
-author("liushl").

-include("scene.hrl").
-include("server.hrl").
-include("common.hrl").
-include("predefine.hrl").
-include("def_act_label.hrl").
-include("guild_war.hrl").
-include("figure.hrl").
-include("def_event.hrl").
-include("rec_event.hrl").
-include("collect.hrl").
-include("errcode.hrl").
-include("battle.hrl").
-include("server_kv.hrl").
-include("attr.hrl").
-include("guild.hrl").
-include("skill.hrl").
%% API
-export([
    is_guild_war_scene/1,               %% 是否公会战场景
    is_during_guild_war/0,              %% 是否公会战期间
    is_escort/1,                        %% 是否采集押运
    rename_guild/2,                     %% 公会改名
    participate_in_guild_war/1,         %% 玩家参与一次公会战
    handle_event/2,
    change_scene_callback/4,
    check_collect/2,                    %% 采集判断
    role_kill_other/2,                  %% 家击杀了采集玩家
    collect_mon/2,                      %% 采集成功
    role_into_convoy_state/2,           %% 进入押运状态
    role_end_convoy_state/1
]).

-export([
    ask_enter_guild_war/2,              %% 请求进入
    enter_scene/2,
    leave_scene/1,                      %% 离开活动场景
    leave_arg/0,                        %% 离开参数
    collect_commit/2,                   %% 采集提交
    collect_commit_do/2,
    ask_top_guild/1                     %% 查看上期明星社团
    , get_cd_time/1
    , use_skill/1
]).

-export([
    get_guild_camp_war_info/2
    ]).

%% 是否公会战场景
is_guild_war_scene(SceneId) ->
    SceneId =:= ?GUILD_WAR_SCENE.

%% 是否公会战期间
is_during_guild_war() ->
    guild_war_mgr:is_during_guild_war().

%% 是否采集押运
is_escort(Player) ->
    lists:keymember(?ACT_LABEL_GUILD_WAR_COLLECTION, 1, Player#player_status.act_label).

%% 公会改名
rename_guild(GuildId, NowGuildName) ->
    guild_war_mgr:rename_guild(GuildId, NowGuildName).

%% 玩家参与一次公会战，进去一下则就算参与
participate_in_guild_war(_RoleId) ->
    ok.

%%% @doc 事件处理
%% 进入场景后
handle_event(Player, #event_callback{type_id = ?EVENT_FIN_CHANGE_SCENE}) ->
    #player_status{
        scene = Scene,
        act_label = ActLabel
    } = Player,
    case is_guild_war_scene(Scene) of
        true  ->
            case lists:keyfind(?ACT_LABEL_GUILD_WAR_COLLECTION, 1, ActLabel) of
                {_, CollectId} ->
                    {ok, Bin} = pt_405:write(40506, [CollectId]),
                    lib_server_send:send_to_sid(Player#player_status.sid, Bin);
                _ ->
                    ok
            end;
        false ->
            ok
    end,
    {ok, Player};

%% 死亡后-更新自己与攻击者的连击数/攻击者加分/自己结束护送状态/攻击者进入护送状态
handle_event(Player, #event_callback{type_id = ?EVENT_PLAYER_DIE, data = #{atter := Atter, attersign := Sign}}) ->
    #player_status{
        id = RoleId,
        scene = SceneId,
        act_label = ActLabel,
        scene_pool_id = PoolId,
        copy_id = CopyId
    } = Player,
    #battle_return_atter{
        id = AttackId
    } = Atter,
    case is_guild_war_scene(SceneId) of
        true  ->
            Sign =:= ?BATTLE_SIGN_PLAYER andalso
                guild_war_mgr:kill_man(AttackId, RoleId, SceneId, PoolId, CopyId),
            case lists:keyfind(?ACT_LABEL_GUILD_WAR_COLLECTION, 1, ActLabel) of
                {_, CollectId} ->
                    Sign =:= ?BATTLE_SIGN_PLAYER andalso
                        lib_player:apply_cast(AttackId, ?APPLY_CAST_STATUS, ?MODULE, role_kill_other, [CollectId]),
                    {ok, role_end_convoy_state(Player)};
                _ ->
                    {ok, Player}
            end;
        false ->
            {ok, Player}
    end;
%% 角色改名
handle_event(Player, #event_callback{type_id = ?EVENT_RENAME, data = Name}) ->
    guild_war_mgr:update_role_info(Player#player_status.id, name, Name),
    {ok, Player};
%% 角色VIP升级
handle_event(Player, #event_callback{type_id = ?EVENT_VIP}) ->
    #player_status{id = RoleId, figure = #figure{vip = Vip}} = Player,
    guild_war_mgr:update_role_info(RoleId, vip, Vip),
    {ok, Player};
%% 角色至尊VIP变化
handle_event(Player, #event_callback{type_id = ?EVENT_SUP_VIP_CHANGE}) ->
    #player_status{id = RoleId, figure = #figure{sup_vip = SupVip}} = Player,
    guild_war_mgr:update_role_info(RoleId, sup_vip, SupVip),
    {ok, Player};
%% 离线
handle_event(Player, #event_callback{type_id = ?EVENT_DISCONNECT}) ->
    #player_status{scene = Scene, scene_pool_id = PoolId} = Player,
    case is_guild_war_scene(Scene) of
        true  ->
            guild_war_mgr:out_scene(PoolId);
        false ->
            ok
    end,
    {ok, Player}.

%% 切换场景时回调
change_scene_callback(Player, {OldSceneId, OldScenePoolId, _OldCopyId, _OldX, _OldY}, _OldSceneData, _NewSceneData) ->
    case is_guild_war_scene(OldSceneId) of
        true  ->
            %% 离开活动场景的时候：取消采集数据/解锁/重新计算一次速度
            Player1 = lib_player:break_action_lock(Player, ?ERRCODE(err405_in_guild_war)),
            Player2 = Player1#player_status{act_label = []},  %% act_label直接置空，目前来看是唯一的
            Player3 = lib_player:update_speed(Player2),
            guild_war_mgr:out_scene(OldScenePoolId),
            {ok, Player3};
        false ->
            {ok, Player}
    end.

%% 采集判断
check_collect(Player, #collect_args{mid = _MonCfgId}) ->
    #player_status{
        scene = SceneId,
        act_label = ActLabel
    } = Player,
    case is_guild_war_scene(SceneId) of
        true  ->
            case lists:keymember(?ACT_LABEL_GUILD_WAR_COLLECTION, 1, ActLabel) of
                true  -> {false, ?ERRCODE(err405_guild_war_repeat_collect)};
                false -> true
            end;
        false -> true
    end.

%%% @doc 玩家击杀了采集玩家-如果对方是押运状态，自己不是押运状态/或者押运品质低，则进入押运状态
role_kill_other(Player, CollectId) ->
    case lists:keyfind(?ACT_LABEL_GUILD_WAR_COLLECTION, 1, Player#player_status.act_label) of
        {_, MyCollectId}  ->
            HighQuality = ?GUILD_WAR_HIGH_QUALITY_MATERIALS,
            case CollectId =:= HighQuality andalso MyCollectId =/= HighQuality of
                true  ->
                    role_into_convoy_state(Player, CollectId);
                false ->
                    Player
            end;
        false ->
            role_into_convoy_state(Player, CollectId)
    end.

%%% @doc 采集成功-记录采集数据
collect_mon(CollectorId, Minfo) ->
    #scene_object{config_id = CollectId, scene = Scene} = Minfo,
    is_guild_war_scene(Scene) andalso
        lib_player:apply_cast(CollectorId, ?APPLY_CAST_STATUS, ?MODULE, role_into_convoy_state, [CollectId]).

%% 玩家成功采集/抢夺别人的押运，进入押运状态-增加头顶标识
role_into_convoy_state(Player, CollectId) ->
    %% 头顶加标识
    Player1 = lib_scene:change_act_label(Player, ?ACT_LABEL_GUILD_WAR_COLLECTION, CollectId),
    Player2 = lib_player:count_player_speed(Player1),
    mod_scene_agent:update(Player1,[{speed, Player2#player_status.battle_attr#battle_attr.speed}]),
    {ok, Bin} = pt_405:write(40506, [CollectId]),
    lib_server_send:send_to_sid(Player#player_status.sid, Bin),
    Player2.

%% 死亡/采集提交-结束押运状态
role_end_convoy_state(Player) ->
    Player1 = lib_scene:change_act_label(Player, ?ACT_LABEL_GUILD_WAR_COLLECTION, 0),
    Player2 = lib_player:count_player_speed(Player1),
    mod_scene_agent:update(Player2,[{speed, Player2#player_status.battle_attr#battle_attr.speed}]),
    {ok, Bin} = pt_405:write(40506, [0]),
    lib_server_send:send_to_sid(Player#player_status.sid, Bin),
    Player2.

%%%-------------------------------------------------------------------
%%% @doc 玩家协议处理
%%%-------------------------------------------------------------------
%% @doc 请求进入
ask_enter_guild_war(Player, Pool) ->
    #player_status{
        id = RoleId,
        figure = #figure{guild_id = GuildId}
    } = Player,
    case lib_scene:is_transferable(Player) of
        {false, Error} -> {false, Error};
        {true, 1} ->
            IsActOpen = is_during_guild_war(),
            if
                GuildId =:= 0 -> {false, ?ERRCODE(err405_has_no_guild)};
                not IsActOpen -> {false, ?ERRCODE(err405_guild_war_not_open)};
                Pool =:= 0 -> enter_scene(Player, 0);
                true ->
                    case scene_mgr:check_lock_enter(RoleId, ?GUILD_WAR_SCENE, Pool - 1, 0, ?SCENE_TYPE_GWAR, ?NODE_GAME) of
                        true  ->
                            enter_scene(Player, Pool);
                        false ->
                            {false, ?ERRCODE(err405_max_role)}
                    end
            end
    end.

enter_scene(Player, PoolId) ->
    #player_status{
        id = RoleId,
        guild = Guild,
        figure = #figure{
            guild_id = GuildId,
            guild_name = GuildName
        }
    } = Player,
    #status_guild{flag = GuildFlag} = Guild,
    RoleInfo = #guild_war_role{
        role_id = RoleId
        , guild_id = GuildId
        , guild_name = GuildName
        , guild_flag = GuildFlag
        , picture = lib_player:trans_to_picture(Player)
    },
    SceneId = ?GUILD_WAR_SCENE,
    case PoolId =:= 0 of
        true  ->
            %% 指定0，则自由分配
            NewPlayer = lib_scene:change_scene(Player, SceneId, 0, 0, 0, 0, [{action_lock, ?ERRCODE(err405_in_guild_war)}]);
        false ->
            %% 前端发过来的分线需要-1
            NewPlayer = lib_scene:change_scene(Player, SceneId, PoolId - 1, 0, 0, 0, false, [{action_lock, ?ERRCODE(err405_in_guild_war)}])
    end,
    Mfa = {guild_war_mgr, success_enter_guild_war, [RoleInfo, NewPlayer#player_status.scene_pool_id]},
    mod_guild:apply_cast(?MODULE, get_guild_camp_war_info, [GuildId, Mfa]),
    {ok, NewPlayer}.

%% @doc 离开活动场景，清除身上的采集
leave_scene(Player) ->
    case is_guild_war_scene(Player#player_status.scene) of
        true  ->
            lib_scene:change_scene(Player, 0, 0, 0, 0, 0, []);
        false ->
            Player
    end.

%% 离开活动做的处理

leave_arg() ->
    [{act_label, [{?ACT_LABEL_GUILD_WAR_COLLECTION, 0}]}, {action_free, ?ERRCODE(err405_in_guild_war)}, {recalc_speed, ok}].

%% @doc 采集提交
collect_commit(Player, Npc) ->
    #player_status{
        x = X,
        y = Y,
        scene = SceneId,
        act_label = ActLabel
    } = Player,
    case data_scene:get(SceneId) of
        #ets_scene{npc = NpcPos} ->
            {C_X, C_Y} = find_pos_xy(Npc, NpcPos),
            CollectInfo = lists:keyfind(?ACT_LABEL_GUILD_WAR_COLLECTION, 1, ActLabel),
            Distance = umath:distance({X, Y}, {C_X, C_Y}),
            if
                Distance > 500 -> {?ERRCODE(err405_guild_war_distance), Player};
                CollectInfo =:= false -> {?ERRCODE(err405_guild_war_no_collection), Player};
                true ->
                    {_, CollectId} = CollectInfo,
                    {1, collect_commit_do(Player, CollectId)}
            end;
        _ ->
            {false, 0}
    end.

find_pos_xy(_, []) -> {0, 0};
find_pos_xy(Npc, [[Npc,X, Y, _]|_]) -> {X, Y};
find_pos_xy(Npc, [_|T]) -> find_pos_xy(Npc, T).

collect_commit_do(Player, CollectId) ->
    ScoreCfg = ?GUILD_WAR_COLLECT_COMMIT_SCORE,
    case lists:keyfind(CollectId, 1, ScoreCfg) of
        {_, AddScore} ->
            guild_war_mgr:add_score(Player#player_status.id, AddScore, collect),
            lib_achievement_api:guild_war_military_event(Player, AddScore),
            role_end_convoy_state(Player);
        _ ->
            Player
    end.

%% @doc 查看上期明星社团
ask_top_guild(Sid) ->
    [{_, GuildId}]    = lib_server_kv:get_value([{?SERVER_KV_GUILD_WAR_TOP_GUILD, 0}]),
    case GuildId > 0 of
        true  ->
            {Chief, _} = lib_guild_api:get_guild_chief(GuildId),
            Chief;
        false ->
            Chief = 0
    end,
    Figure     = lib_role:get_role_figure(Chief),
    {ok, Bin}  = pt_405:write(40509, [Figure]),
    lib_server_send:send_to_sid(Sid, Bin).


%% 社团进程执行
get_guild_camp_war_info(GuildId, Mfa) ->
    CampWarInfo = 
    case lib_guild_data:get_guild_by_id(GuildId) of
        [] -> [0, <<>>, 0, 0];
        Guild ->
            #guild{chief_id = ChiefId, chief_name = ChiefName, combat_power = GuildPower} = Guild,
            #figure{power = ChiefPower} = lib_role:get_role_figure(ChiefId),
            [ChiefId, ChiefName, ChiefPower, GuildPower]
    end,
    {Mod, Fun, Args} = Mfa,
    apply(Mod, Fun, [CampWarInfo|Args]),
    ok.

%% 技能CD
get_cd_time(RoleId) ->
    case erlang:get({?MODULE, RoleId}) of
        Time when is_integer(Time) ->
            Time;
        _ ->
            0
    end.

set_cd(RoleId, CDTime) ->
    erlang:put({?MODULE, RoleId}, CDTime).

%% hi使用技能
use_skill(Player) ->
    InScene = is_guild_war_scene(Player#player_status.scene),
    case InScene of
        true  ->
            CdTime = get_cd_time(Player#player_status.id),
            Now = utime:unixtime(),
            case Now >= CdTime of
                true  ->
                    SkillId = ?SP_SKILL_DEL_HURT_GWAR,
                    case data_skill:get(SkillId, 1) of
                        #skill{lv_data = #skill_lv{cd = CD}} ->
                            CD;
                        _ ->
                            CD = 60
                    end,
                    NextCD = Now + CD div 1000,
                    set_cd(Player#player_status.id, NextCD),
                    lib_skill_buff:add_buff(Player, SkillId, 1),
                    [1, NextCD];
                false ->
                    [?ERRCODE(err405_skill_cd), CdTime]
            end;
        false ->
            ok
    end.
