%%%-------------------------------------------------------------------
%%% @author liushl
%%% @doc
%%%     活动：抛接球，一方邀请，另一方同意则开始。
%%% 玩家点击屏幕中央球开始游戏，同时将球传给对方。
%%% 球往自己方向飞来，点击球所在区域则可传给对方。
%%% 球往自己方向飞来，没有点击球所在区域，球落地则游戏结束，进入结算界面
%%% @end
%%%-------------------------------------------------------------------
-module(mate_catch_ball).
-author("liushl").

-include("mate.hrl").
-include("common.hrl").
-include("def_act_label.hrl").
-include("def_module.hrl").
-include("errcode.hrl").

-define(MATE_ACT_CATCH_BALL_FLY_TIME, 4000).  %% 球的最长飞行时间
%% 抛接球 玩法事件
-define(MATE_ACT_CATCH_BALL_READY,       1). % 准备
-define(MATE_ACT_CATCH_BALL_BEGIN,       2). % 游戏开始
-define(MATE_ACT_CATCH_BALL_TAP,         3). % 玩家点击
-define(MATE_ACT_CATCH_BALL_END,         4). % 游戏结算
%% API
-export([handle_event/3]).

%% 玩家回应同意 等开球 10秒后自动开球
handle_event({mate_act_response_yes, DailyScores}, #mate_act{key = Key, data = undefined} = ActInfo, State) ->
    ActData = #mate_catch_ball{},
    broadcast_event(Key, ?MATE_ACT_CATCH_BALL_READY, ActData, Key),
    NewMateAct = lists:keyreplace(
        ActInfo#mate_act.key,
        #mate_act.key,
        State#mate_mgr.mate_act,
        ActInfo#mate_act{daily_score = DailyScores, data = #mate_catch_ball{}}
    ),
    State#mate_mgr{mate_act = NewMateAct};
%% 准备好 等开球 10秒后自动开球
handle_event(all_get_ready, #mate_act{key = Key, data = ActData} = ActInfo, State) ->
    Ref = mate_mgr:set_mate_act_timer(100000, self(), Key, mate_catch_ball_auto),
    NewActData = ActData#mate_catch_ball{ref = Ref},
    NewMateAct = lists:keyreplace(
        ActInfo#mate_act.key,
        #mate_act.key,
        State#mate_mgr.mate_act,
        ActInfo#mate_act{data = NewActData, time = utime:unixtime()}
    ),
    State#mate_mgr{mate_act = NewMateAct};
%% 玩家没点击，则自动开球
handle_event(mate_catch_ball_auto, #mate_act{key = Key, data = #mate_catch_ball{catch_role = 0}} = ActInfo, State) ->
    Role = mate_mgr:rand_role(Key),
    handle_event({mate_catch_ball_begin, Role}, ActInfo, State);
%% 开球
handle_event({mate_catch_ball_begin, Role}, #mate_act{key = Key, data = #mate_catch_ball{catch_role = 0} = ActData} = ActInfo, State) ->
    NewActData = ActData#mate_catch_ball{
        hits = -1 % 开球时不算，先-1
        , catch_role = Role
    },
    broadcast_event(Key, ?MATE_ACT_CATCH_BALL_BEGIN, NewActData, Role),
    handle_event({mate_catch_ball_catch, Role}, ActInfo#mate_act{data = NewActData}, State);
%% 击球
handle_event({mate_catch_ball_catch, Role}, #mate_act{key = Key, data = #mate_catch_ball{catch_role = Role} = ActData} = ActInfo, State) ->
    #mate_catch_ball{ref = OldRef, hits = Hits} = ActData,
    CatchRole = mate_mgr:get_target_role(Key, Role),
    util:cancel_timer(OldRef),
    Ref = mate_mgr:set_mate_act_timer(?MATE_ACT_CATCH_BALL_FLY_TIME, self(), Key, mate_catch_ball_land),
    NewHits = Hits+1,
    NewActData = ActData#mate_catch_ball{
        catch_role = CatchRole,
        ref = Ref,
        hits = NewHits
    },
    broadcast_event(Key, ?MATE_ACT_CATCH_BALL_TAP, NewActData, Role),
    NewMateAct = lists:keyreplace(Key, #mate_act.key, State#mate_mgr.mate_act, ActInfo#mate_act{data = NewActData}),
    State#mate_mgr{mate_act = NewMateAct};
%% 球落地游戏结束，结算
handle_event(mate_catch_ball_land, #mate_act{key = {RoleA, RoleB} = Key, data = ActData, daily_score = DailyScores, time = Time}=_ActInfo, State) ->
    broadcast_event(Key, ?MATE_ACT_CATCH_BALL_END, ActData, []),
    %% 结算
    settlement(RoleA, ActData#mate_catch_ball.hits, lists:keyfind(RoleA, 1, DailyScores), Time),
    settlement(RoleB, ActData#mate_catch_ball.hits, lists:keyfind(RoleB, 1, DailyScores), Time),
    free_role(RoleA),
    free_role(RoleB),
    NewMateAct = lists:keydelete(Key, #mate_act.key, State#mate_mgr.mate_act),
    %?ERR("mate_catch_ball_land:~p~n", [ActInfo]),
    State#mate_mgr{mate_act = NewMateAct};
%% 玩家退出/直接结算
handle_event(mate_act_quit, #mate_act{data = #mate_catch_ball{ref = Ref, hits = Hits} = ActData, key = {RoleA, RoleB}, time = Time, daily_score = DailyScores}, State) ->
    util:cancel_timer(Ref),
    %% 结算
    settlement(RoleA, Hits, lists:keyfind(RoleA, 1, DailyScores), Time),
    settlement(RoleB, Hits, lists:keyfind(RoleB, 1, DailyScores), Time),
    broadcast_event({RoleA, RoleB}, ?MATE_ACT_CATCH_BALL_END, ActData, []),
    State;
%% 重新上线：游戏正在玩/可以继续玩
handle_event({login, RoleId}, #mate_act{data = ActData, key = Key}, State) ->
    %% 给玩家发一些数据：当前可点击玩家/当前成绩
    case ActData of
        #mate_catch_ball{} ->
            Bin1 = pack_data(?MATE_ACT_CATCH_BALL_READY, ActData, Key),
            Bin2 = pack_data(?MATE_ACT_CATCH_BALL_TAP, ActData, []),
            lib_server_send:send_to_uid(RoleId, <<Bin1/binary, Bin2/binary>>),
            lib_scene:change_act_label(RoleId, ?ACT_LABEL_MATE_CATCH_BALL, 1),
            lib_player:setup_action_lock(RoleId, ?ERRCODE(err149_on_game));
        _ ->
            ok
    end,
    State;
handle_event(_Msg, _ActInfo, State) ->
    %io:format("~p, ~p: ~p, ~p", [?MODULE, ?LINE, _Msg, _ActInfo]),
    State.

%% 事件广播
broadcast_event({RoleA, RoleB}, Event, Record, Other) ->
    Bin = pack_data(Event, Record, Other),
    lib_server_send:send_to_uid(RoleA, Bin),
    lib_server_send:send_to_uid(RoleB, Bin).

pack_data(Event, Record, Other) ->
    #mate_catch_ball{
        catch_role = CatchRole     % 当前可点击玩家
        , hits = Hits              % 击球次数
    } = Record,
    case Event of
        ?MATE_ACT_CATCH_BALL_READY ->
            {RoleA, RoleB} = Other,
            {ok, Bin} = pt_149:write(14935, [[lib_role:get_role_figure(RoleA), lib_role:get_role_figure(RoleB)]]);
        ?MATE_ACT_CATCH_BALL_BEGIN ->
            {ok, Bin} = pt_149:write(14936, [Other]);
        ?MATE_ACT_CATCH_BALL_TAP ->
            {ok, Bin} = pt_149:write(14938, [CatchRole, Hits]);
        ?MATE_ACT_CATCH_BALL_END ->
            {ok, Bin} = pt_149:write(14939, [Hits])
    end,
    Bin.

settlement(RoleId, Score, {RoleId, DailyScore}, Time) ->
    MateScoreLv = data_mate:get_mate_catch_ball_lv(Score),
    DailyLv = data_mate:get_mate_catch_ball_lv(DailyScore),
    case MateScoreLv > DailyLv of
        true  ->
            case utime:is_today(Time) of
                true  ->
                    %% 按游戏开始时的成绩进行比较，跨天不记录成绩
                    lib_daily:set_count_offline(RoleId, ?MOD_MATE, ?MATE_ACT_CATCH_BALL, Score);
                false ->
                    ok
            end,
            Award = calc_award(DailyLv, MateScoreLv, []),

            lib_goods_api:send_reward_with_mail(RoleId, Award, mate_catch_ball, "");
        false ->
            ok
    end;
settlement(_, _, _, _) -> ok.

free_role(RoleId) ->
    %% 给玩家去掉标识
    lib_scene:change_act_label(RoleId, ?ACT_LABEL_MATE_CATCH_BALL, 0),
    lib_player:break_action_lock(RoleId, ?ERRCODE(err149_on_game)).

calc_award(MaxLv, MaxLv, Award) -> Award;
calc_award(Lv, MaxLv, Award) ->
    calc_award(Lv+1, MaxLv, data_mate:get_mate_catch_ball_award(Lv+1) ++ Award).