-module (lib_act_join_mod).
-include ("common.hrl").
-include ("rec_act_join.hrl").

-export ([
	init/0,
	daily_clear/2,
	add_join/2,
	to_db/1,
	stop/1,
	get_join/2,
	clear_module/2,
	quit_guild/2
]).

%% 初始化参与记录
init() ->
	delete_join_log_db(),
	List = load_join_log_db(),
	JoinMap = init_helper(List, #{}),
	NewState = #act_join_state{join_map = JoinMap},
	{ok, NewState}.

init_helper([], JoinMap) -> JoinMap;
init_helper([[PlayerId, GuildId, ModuleId, Time]|T], JoinMap) ->
	ModuleJoin 	= maps:get(ModuleId, JoinMap, #{}),
	JoinPlayer 	= make(join_player, {PlayerId, GuildId, ModuleId, Time}),
	NewModuleJoin = maps:put(PlayerId, JoinPlayer, ModuleJoin),
	NewJoinMap 	= maps:put(ModuleId, NewModuleJoin, JoinMap),
	init_helper(T, NewJoinMap).

make(join_player, {PlayerId, GuildId, ModuleId, Time}) ->
	#join_player{
		player_id = PlayerId,
		guild_id  = GuildId,
		module_id = ModuleId,
		time      = Time
	}.

%% 日清：活动参与记录
daily_clear({_DelaySec}, _State) ->
	{ok, NewState} = init(),
	{ok, NewState}.

%% 添加参与记录
add_join({PlayerId, GuildId, ModuleId}, State) ->
	#act_join_state{
		join_map = JoinMap} = State,
	ModuleJoin 	= maps:get(ModuleId, JoinMap, #{}),
	JoinPlayer 	= make(join_player, {PlayerId, GuildId, ModuleId, utime:unixtime()}),
	NewState = do_add_join(JoinPlayer, ModuleJoin, State),
	{ok, NewState}.

do_add_join(JoinPlayer, ModuleJoin, State) ->
	#join_player{
		player_id = PlayerId, guild_id = GuildId, module_id = ModuleId} = JoinPlayer,
	#act_join_state{
		join_map = JoinMap, add_num  = AddNum, add_list = AddList} = State,
	case maps:get(PlayerId, ModuleJoin, false) of
		false ->
			lib_log_api:join_log(PlayerId, GuildId, ModuleId),
			NewModuleJoin = maps:put(PlayerId, JoinPlayer, ModuleJoin),
			NewJoinMap 	= maps:put(ModuleId, NewModuleJoin, JoinMap),
			NewState = State#act_join_state{
				join_map = NewJoinMap, add_num  = AddNum+1, add_list = [JoinPlayer|AddList]},
			LastState = reset_ref(NewState),
			LastState;
		_ -> State
	end.

-define(WRITE_TIME, 5000).
-define(WRITE_NUM, 50).
reset_ref(State) ->
	case State#act_join_state.ref of
		[] ->
			Ref = util:send_after([], 10, self(), {to_db}),
			State#act_join_state{ref = Ref};
		OldRef when State#act_join_state.add_list==[] ->
			util:cancel_timer(OldRef),
			State#act_join_state{ref = []};
		OldRef ->
			Ref = util:send_after(OldRef, ?WRITE_TIME, self(), {to_db}),
			State#act_join_state{ref = Ref}
	end.

%% 入库操作
to_db(State) ->
	#act_join_state{
		add_num = AddNum,
		add_list = AddList
	} = State,
	case AddNum>?WRITE_NUM of
		true ->
			NewAddNum = AddNum - ?WRITE_NUM,
			{Pre, Post} = lists:split(?WRITE_NUM, AddList);
		false ->
			NewAddNum = 0,
			Pre = AddList, Post = []
	end,
	spawn(fun() -> to_db_helper(Pre, 0) end),
	NewState= State#act_join_state{
		add_num = NewAddNum,
		add_list = Post
	},
	LastState = reset_ref(NewState),
	{ok, LastState}.

%% 关闭服务处理
stop(State) ->
	#act_join_state{
		add_list = AddList
	} = State,
	to_db_helper(AddList, 0),
	NewState = State#act_join_state{
		add_num = 0,
		add_list= []
	},
	LastState = reset_ref(NewState),
	{ok, LastState}.

to_db_helper([], _I) -> skip;
to_db_helper([JoinPlayer|T], I) ->
	case I rem 10 of
        0 -> timer:sleep(200);
        _ -> skip
    end,
	#join_player{
		player_id = PlayerId,
		guild_id  = GuildId,
		module_id = ModuleId,
		time      = Time
	} = JoinPlayer,
	replace_join_log_db(PlayerId, GuildId, ModuleId, Time),
	to_db_helper(T, I+1).

%% 获取参与一个活动的玩家(最近2个小时数据，用于拍卖分红)
get_join({ModuleId}, State) ->
	NowTime = utime:unixtime(),
	#act_join_state{join_map = JoinMap} = State,
	ModuleJoin 	= maps:get(ModuleId, JoinMap, #{}),
	[{PlayerId, GuildId}||#join_player{player_id = PlayerId, guild_id = GuildId, time = Time}
		<- maps:values(ModuleJoin), Time + 2*3600> NowTime].

%% 清除一个活动参与记录
clear_module({ModuleId}, State) ->
	#act_join_state{
		join_map = JoinMap
	} = State,
	case catch delete_join_log_module_db(ModuleId) of
		ok -> skip;
		Error -> ?ERR("clear_module:~p~n", [Error])
	end,
	NewJoinMap = maps:remove(ModuleId, JoinMap),
	{ok, State#act_join_state{join_map = NewJoinMap} }.

%% 退出公会，清除活动参与记录
quit_guild({PlayerId}, State) ->
	#act_join_state{
		join_map = JoinMap
	} = State,
	case catch delete_join_log_player_db(PlayerId) of
		ok -> skip;
		Error -> ?ERR("quit_guild:~p~n", [Error])
	end,
	NewJoinMap = maps:fold(
		fun(ModuleId, ModuleJoin, Map) ->
			NewModuleJoin = maps:remove(PlayerId, ModuleJoin),
			maps:put(ModuleId, NewModuleJoin, Map)
		end,
		JoinMap, JoinMap),
	{ok, State#act_join_state{join_map = NewJoinMap} }.

%% ------------------------------- db function %% ----------------------------

load_join_log_db() ->
	db:get_all(io_lib:format(?SQL_JOIN_LOG_SELECT, []) ).

replace_join_log_db(PlayerId, GuildId, ModuleId, Time) ->
	db:execute(io_lib:format(?SQL_JOIN_LOG_REPLACE, [PlayerId, GuildId, ModuleId, Time]) ),
	ok.

delete_join_log_db() ->
	UnixDate = utime:unixdate(),
	db:execute(io_lib:format(?SQL_JOIN_LOG_DELETE_LOG, [UnixDate]) ),
	ok.

delete_join_log_module_db(ModuleId) ->
	db:execute(io_lib:format(?SQL_JOIN_LOG_DELETE_MODULE, [ModuleId]) ),
	ok.

delete_join_log_player_db(PlayerId) ->
	db:execute(io_lib:format(?SQL_JOIN_LOG_DELETE_PLAYER, [PlayerId]) ),
	ok.
