%%%-------------------------------------------------------------------
%%% @author linjinyuan
%%% @copyright (C) 2020, <COMPANY>
%%% @doc
%%%     活动：每日登陆
%%% @end
%%% Created : 13. 10月 2020 11:09
%%%-------------------------------------------------------------------
-module(sign_reward).

-include("errcode.hrl").
-include("custom_act.hrl").
-include("server.hrl").
-include("def_fun.hrl").
-include("common.hrl").
-include("rec_event.hrl").
-include("def_event.hrl").
-include("goods.hrl").
-include("figure.hrl").

%% API
-export([
    receive_reward/4,
    ask_reward_status/3,
    count_reward_status/4,
    handle_event/2
]).

%% 领取奖励
receive_reward(Player, ActType, SubType, GradeId) ->
    #custom_act_data{act_data = ActData} = CustomActData = lib_custom_act_data:custom_act_data(ActType, SubType),
    NowTime = utime:unixtime(),
    Result =
        case lib_custom_act_util:get_custom_act_open_info(ActType, SubType) of
            #act_info{wlv = WLv, etime = Etime} when NowTime < Etime ->
                case lib_custom_act_util:get_act_reward_cfg_info(ActType, SubType, GradeId) of
                    RewardCfg when is_record(RewardCfg, custom_act_reward_cfg) ->
                        case lists:keyfind(GradeId, 1, ActData) of
                            {GradeId, ?ACT_REWARD_CAN_NOT_GET} -> {false, ?ERRCODE(err331_act_can_not_get)};
                            {GradeId, ?ACT_REWARD_HAS_GET} -> {false, ?ERRCODE(err331_already_get_reward)};
                            {GradeId, Status} ->
                                do_receive_reward(Player, ActType, SubType, GradeId, Status, CustomActData, RewardCfg, WLv);
                            _ -> {false, ?ERRCODE(err331_no_act_reward_cfg)}
                        end;
                    _ -> {false, ?ERRCODE(err331_no_act_reward_cfg)}
                end;
            _ ->
                {false, ?ERRCODE(err331_act_closed)}
        end,
    case Result of
        {true, NewPlayer} -> ErrCode = ?SUCCESS;
        {false, ErrCode} -> NewPlayer = Player
    end,
    {ok, BinData} = pt_331:write(33105, [ErrCode, ActType, SubType, GradeId]),
    lib_server_send:send_to_sid(Player#player_status.sid, BinData),
    {ok, NewPlayer}.

do_receive_reward(Player, ActType, SubType, GradeId, Status, CustomActData, RewardCfg, WLv) ->
    #custom_act_reward_cfg{condition = Condition, reward = RewardList} = RewardCfg,
    case check_receive_reward(Player, Status, Condition) of
        {true, NewPlayer} ->
            #custom_act_data{act_data = ActData} = CustomActData,
            NewActData = lists:keystore(GradeId, 1, ActData, {GradeId, ?ACT_REWARD_HAS_GET}),
            NewActData1 = update_act_data(ActType, SubType, GradeId, NewActData),
            lib_custom_act_data:save_custom_data(NewPlayer#player_status.id, CustomActData#custom_act_data{act_data = NewActData1}),
            Produce = #produce{
                type    = custom_act,
                subtype = ActType,
                reward  = RewardList,
                remark  = util:term_to_string(SubType)
            },
            NewPs = lib_goods_api:send_reward(NewPlayer, Produce),
            %% 日志
            #player_status{figure = #figure{lv = Lv, vip = Vip}} = Player,
            LogExtra = lib_custom_act_dispatcher:get_extra_log(RewardCfg),
            lib_log_api:log_custom_act_reward(NewPlayer#player_status.id, ActType, SubType, GradeId, WLv, RewardList, LogExtra
                , Vip, Lv, Player#player_status.gold, NewPs#player_status.gold, Player#player_status.bgold, NewPs#player_status.bgold, utime:unixtime()),
            {true, NewPs};
        {false, Res} -> {false, Res}
    end.

%% 检查奖励状态
check_receive_reward(Player, Status, Conditions) ->
    case Status of
        ?ACT_REWARD_CAN_GET -> {true, Player};
        _ ->
            case lists:keyfind(extra_sign, 1, Conditions) of
                {extra_sign, Cost} ->
                    case lib_goods_api:cost_object_list_with_check(Player, Cost, sign_in_for_gifts, "") of
                        {true, NewPs, _} ->
                            {true, NewPs};
                        {false, Res, _} ->
                            {false, Res}
                    end;
                _ -> {false, ?MISSING_CONFIG}
            end
    end.

%% 更新奖励状态
update_act_data(ActType, SubType, GradeId, ActData) when GradeId < 100 ->
    update_data(ActType, SubType, ActData);
update_act_data(_ActType, _SubType, _GradeId, ActData) ->
    ActData.

update_data(ActType, SubType, ActData) ->
    F = fun({GId, Status}, Acc) ->
        if
            GId < 100 andalso Status =:= ?ACT_REWARD_HAS_GET -> Acc + 1;
            true -> Acc
        end
        end,
    Count = lists:foldl(F, 0, ActData),
    F1 = fun({GId, Status}, Acc) ->
        if
            GId >= 100 ->
                case lib_custom_act_util:get_act_reward_cfg_info(ActType, SubType, GId) of
                    RewardCfg when is_record(RewardCfg, custom_act_reward_cfg) ->
                        Conditions = RewardCfg#custom_act_reward_cfg.condition,
                        case lists:keyfind(sign_count, 1, Conditions) of
                            {sign_count, SignCount} when Count >= SignCount andalso Status =/= ?ACT_REWARD_HAS_GET ->
                                [{GId, ?ACT_REWARD_CAN_GET} | Acc];
                            _ ->
                                [{GId, Status} | Acc]
                        end;
                    _ -> Acc
                end;
            true -> [{GId, Status} | Acc]
        end
         end,
    lists:foldl(F1, [], ActData).

%% 请求奖励状态信息
ask_reward_status(Player, ActType, SubType) ->
    NowTime = utime:unixtime(),
    #player_status{id = RoleId} = Player,
    case lib_custom_act_util:get_custom_act_open_info(ActType, SubType) of
        #act_info{
            etime = Etime
        } = ActInfo when NowTime < Etime ->
            #act_info{key = {Type, SubType}} = ActInfo,
            #custom_act_data{act_data = ActData} = CustomActData = lib_custom_act_data:custom_act_data(ActType, SubType),
            GradeIds = lib_custom_act_util:get_act_reward_grade_list(Type, SubType),
            NewActData =
                case ActData of
                    [] ->
                        init_act_data(Type, SubType, GradeIds);
                    _ ->
                        ActData
                end,
            ?IF(NewActData =/= ActData, lib_custom_act_data:save_custom_data(RoleId, CustomActData#custom_act_data{act_data = NewActData}), skip),
            F = fun(GradeId, Acc) ->
                case lib_custom_act_util:get_act_reward_cfg_info(Type, SubType, GradeId) of
                    #custom_act_reward_cfg{
                        name = Name,
                        desc = Desc,
                        condition = Condition,
                        format = Format,
                        reward = Reward
                    } ->
                        Status = get_grade_status(NewActData, GradeId),
                        ConditionStr = util:term_to_string(Condition),
                        RewardStr = util:term_to_string(Reward),
                        [{GradeId, Format, 0, Status, 0, Name, Desc, ConditionStr, RewardStr} | Acc];
                    _ -> Acc
                end
                end,
            PackList = lists:foldl(F, [], GradeIds),
            {ok, BinData} = pt_331:write(33104, [Type, SubType, PackList]),
            lib_server_send:send_to_sid(Player#player_status.sid, BinData);
        _ ->
            lib_custom_act:send_error_code(Player#player_status.id, ?ERRCODE(err331_act_closed))
    end.

count_reward_status(Player, ActInfo, _Progress, RewardCfg) ->
    case lib_custom_act_check:check_reward_receive_times(Player, ActInfo, RewardCfg) of
        false -> ?ACT_REWARD_HAS_GET;
        _ ->
            case lib_custom_act_check:check_receive_reward_conditions(Player, ActInfo, RewardCfg) of
                {false, ErrorCode} ->
                    case ErrorCode =:= ?ERRCODE(err331_act_time_out) of
                        true -> ?ACT_REWARD_TIME_OUT;
                        false -> ?ACT_REWARD_CAN_NOT_GET
                    end;
                _ -> ?ACT_REWARD_CAN_GET
            end
    end.

%% 初始化奖励状态
init_act_data(Type, SubType, GradeIds) ->
    NowTime = utime:unixtime(),
    case lib_custom_act_util:get_custom_act_open_info(Type, SubType) of
        #act_info{stime = Stime, etime = Etime} when NowTime < Etime ->
            F = fun(GradeId, Acc) ->
                if
                    is_list(Acc) ->
                        case lib_custom_act_util:get_act_reward_cfg_info(Type, SubType, GradeId) of
                            RewardCfg when is_record(RewardCfg, custom_act_reward_cfg) ->
                                case check_reward_status(Stime, RewardCfg) of
                                    false -> false;
                                    Status -> [{GradeId, Status} | Acc]
                                end;
                            _ -> {false, ?ERRCODE(err331_no_act_reward_cfg)}
                        end;

                    true -> false
                end
                end,
            case lists:foldl(F, [], GradeIds) of
                RewardStatus when is_list(RewardStatus) -> RewardStatus;
                false -> []
            end;
        _ ->
            {false, ?ERRCODE(err331_act_closed)}
    end.

get_grade_status(ActData, GradeId) ->
    case lists:keyfind(GradeId, 1, ActData) of
        {GradeId, Status} -> Status;
        _ -> false
    end.

check_reward_status(Stime, RwCfg) ->
    #custom_act_reward_cfg{
        condition = Conditions
    } = RwCfg,
    [Condition | _] = Conditions,
    ActDay = utime:day_span(Stime),
    case Condition of
        {sign_day, Day} ->
            if
                Day =:= ActDay ->
                    ?ACT_REWARD_CAN_GET;
                Day > ActDay ->
                    ?ACT_REWARD_CAN_NOT_GET;
                true ->
                    ?ACT_REWARD_TIME_OUT
            end;
        {sign_count, _SignCount} ->
            ?ACT_REWARD_CAN_NOT_GET;
        _ ->
            false
    end.

%% 登录事件延后
handle_event(Player, #event_callback{type_id = ?EVENT_LOGIN_CAST}) ->
    update_reward_status(Player),
    {ok, Player};

%% 0点事件
handle_event(Player, #event_callback{type_id = ?EVENT_ZERO_CLOCK}) ->
    update_reward_status(Player),
    {ok, Player}.

update_reward_status(Player) ->
    CheckTypes = [?CUSTOM_ACT_TYPE_SIGN_REWARD],
    [
        update_reward_status(Player, Type, SubType) || Type <- CheckTypes,
        #act_info{key = {_, SubType}} <- lib_custom_act_api:get_open_custom_act_infos(Type)
    ].

update_reward_status(Player, ActType, SubType) ->
    #custom_act_data{act_data = ActData} = CustomActData = lib_custom_act_data:custom_act_data(ActType, SubType),
    GradeIds = lib_custom_act_util:get_act_reward_grade_list(ActType, SubType),
    case lib_custom_act_util:get_custom_act_open_info(ActType, SubType) of
        #act_info{stime = Stime} ->
            ActDay = utime:day_span(Stime),
            F = fun(GradeId, Acc) ->
                if
                    GradeId < 100 ->
                        case lib_custom_act_util:get_act_reward_cfg_info(ActType, SubType, GradeId) of
                            RewardCfg when is_record(RewardCfg, custom_act_reward_cfg) ->
                                Condition = RewardCfg#custom_act_reward_cfg.condition,
                                case lists:keyfind(sign_day, 1, Condition) of
                                    {sign_day, Day} when Day =< ActDay ->
                                        case lists:keyfind(GradeId, 1, ActData) of
                                            {GradeId, Status} when Day =:= ActDay andalso Status =/= ?ACT_REWARD_HAS_GET ->
                                                lists:keystore(GradeId, 1, Acc, {GradeId, ?ACT_REWARD_CAN_GET});
                                            {GradeId, Status} when Day < ActDay andalso Status == ?ACT_REWARD_CAN_NOT_GET ->
                                                lists:keystore(GradeId, 1, Acc, {GradeId, ?ACT_REWARD_TIME_OUT});
                                            _ -> Acc
                                        end;
                                    _ -> Acc
                                end;
                            _ -> Acc
                        end;
                    true -> Acc
                end
                end,
            NewActData = lists:foldl(F, ActData, GradeIds),
            NewActData1 = update_data(ActType, SubType, NewActData),
            lib_custom_act_data:save_custom_data(Player#player_status.id, CustomActData#custom_act_data{act_data = NewActData1}),
            pp_custom_act:handle(33104, Player, [ActType, SubType]);
        _ ->
            {false, ?ERRCODE(err331_act_closed)}
    end.
