%%%----------------------------------------------------------------------
%%% @Module  : mod_week
%%% @Author  : HHL
%%% @Created : 2014.07.17
%%% @Description: 每周记录器

%%% Modified: 18/10/2016 by hekai <1472524632@qq.com>
%%% Note: 重构记录器，记录器id由功能模块id跟type类型id唯一确定
%%%       功能模块跟type类型在后台配置注册使用
%%% Usage:
%%% mod_week:get_count(RoleId, ?PET, ?FREE_GROW_LV).
%%% mod_week:increment(RoleId, ?PET, ?FREE_GROW_LV).
%%% ?PET::integer()，在后台及def_module.hrl中定义
%%% ?FREE_GROW_LV::integer()，在后台及def_week.hrl中定义

%%% 20200922不在单独启动进程管理
%%%----------------------------------------------------------------------
-module(mod_week).
-include("week.hrl").
-include("server.hrl").
-include("common.hrl").
-include("def_event.hrl").
-include("rec_event.hrl").
-compile(export_all).
-export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2, code_change/3]).
-export([
    handle_event/2
    ]).
-define(get_module_pid(RoleId), misc:get_week_process(RoleId)).


%% 下线操作
stop(Pid) ->
    gen_server:cast(Pid, stop).

start_link(RoleId) ->
    gen_server:start_link(?MODULE, [RoleId], []).

init([RoleId]) ->
    lib_week:online(RoleId),
    misc:register(global, misc:week_process_name(RoleId), self()),
    {ok, ?MODULE}.

%%每周清空缓存
handle_cast({week_clear,CounterType}, Status) ->
    erase(?WEEK_KEY(CounterType)),
    {noreply, Status};

%%停止任务进程
handle_cast(stop, Status) ->
    {stop, normal, Status};

%% cast数据调用
handle_cast({Fun, Arg}, Status) ->
    apply(lib_week, Fun, Arg),
    {noreply, Status};

handle_cast(_R , Status) ->
    {noreply, Status}.

%% call数据调用
handle_call({Fun, Arg} , _FROM, Status) ->
    {reply, apply(lib_week, Fun, Arg), Status};

handle_call(_R , _FROM, Status) ->
    {reply, ok, Status}.

handle_info(_Reason, Status) ->
    {noreply, Status}.

terminate(_Reason, Status) ->
    {ok, Status}.

code_change(_OldVsn, Status, _Extra)->
    {ok, Status}.



%%--------------以下有效函数-------------------

handle_event(Status, #event_callback{type_id = ?EVENT_ZERO_CLOCK})->
    case utime:logic_day_of_week() of
        1->
            CounterType = ?WEEK_TYPE_ZERO,
            erase(?WEEK_KEY(CounterType)),
            LastStatus = lib_player_tomorrow:week(Status, CounterType),
            {ok, LastStatus};
        _->
            {ok,Status}
    end;
handle_event(Status, #event_callback{type_id = ?EVENT_FOUR_CLOCK})->
    case utime:logic_day_of_week() of
        1->
            CounterType = ?WEEK_TYPE_FOUR,
            erase(?WEEK_KEY(CounterType)),
            LastStatus = lib_player_tomorrow:week(Status, CounterType),
            {ok, LastStatus};
        _->
            {ok,Status}
    end;
handle_event(PS, _) ->
    {ok, PS}.


week_clear()->
    week_clear_zero(),
    week_clear_four().

%% 每周数据清除
week_clear_zero() ->
    week_clear(?WEEK_TYPE_ZERO).
week_clear_four() ->
    week_clear(?WEEK_TYPE_FOUR).

week_clear(CounterType) ->
    %% 启动新进程，并随机延时，不阻塞主进程
    spawn(fun() ->
                %% 周计数器已经通过时间戳来控制更新，所以数据库中数据清理可以延迟操作，避开IO高峰期
                WeekDividing = lib_week:week_dividing(CounterType, utime:unixtime()),
                SqlFmt =
                case CounterType of
                    ?WEEK_TYPE_ZERO -> ?SQL_WEEK_ZERO_CLEAR;
                    _               -> ?SQL_WEEK_FOUR_CLEAR
                end,
                Sql = io_lib:format(SqlFmt, [WeekDividing]),
                DiffTime = urand:rand(600, 700) * 1000,
                timer:sleep(DiffTime),
                db:execute(Sql)
        end).



%% 后台使用,清除所有人的周常
week_clear_all_houtai() ->
    mod_week:week_clear().


%% 清除某玩家的所有周常(只能用于在线玩家)
week_clear_role_all(RoleId) ->
    db:execute(io_lib:format(?SQL_WEEK_ZERO_ROLE_CLEAR, [RoleId])),
    db:execute(io_lib:format(?SQL_WEEK_FOUR_ROLE_CLEAR, [RoleId])),
    erase(?WEEK_KEY(?WEEK_TYPE_ZERO)),
    erase(?WEEK_KEY(?WEEK_TYPE_FOUR)).
