%%%--------------------------------------
%%% @Module  : mod_perfect_lover
%%% @Author  : huyihao
%%% @Created : 2018.03.15
%%% @Description:  完美情人(三世恋人)
%%%--------------------------------------
-module(mod_perfect_lover).

-include("errcode.hrl").
-include("common.hrl").
-include("def_module.hrl").
-include("custom_act.hrl").
-include("perfect_lover.hrl").
-include("predefine.hrl").
-include("language.hrl").

-behaviour(gen_server).

-export([start_link/0]).
-export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2, code_change/3]).
-export([act_start/1, act_close/1, add_wedding_times/3, open_perfect_lover/4, send_reward/3]).

start_link() ->
    gen_server:start_link({local, ?MODULE}, ?MODULE, [], []).

act_start(ActSubType) ->
    gen_server:cast(?MODULE, {act_start, ActSubType}).

act_close(ActSubType) ->
    gen_server:cast(?MODULE, {act_close, ActSubType}).

add_wedding_times(RoleIdM, RoleIdW, WeddingType) ->
    gen_server:cast(?MODULE, {add_wedding_times, RoleIdM, RoleIdW, WeddingType}).

open_perfect_lover(SubType, RoleId, LoverRoleId, LoverName) ->
    gen_server:cast(?MODULE, {open_perfect_lover, SubType, RoleId, LoverRoleId, LoverName}).

send_reward(SubType, RoleId, WeddingType) ->
    gen_server:cast(?MODULE, {send_reward, SubType, RoleId, WeddingType}).

init([]) ->
    case lib_custom_act_api:get_open_subtype_ids(?CUSTOM_ACT_TYPE_PERFECT_LOVER) of
        [] -> %% 若活动尚未开始、清空所有状态
            ActSubType = 0,
            WeddingTimesList = [],
            WeddingLogList = [],
            RewardState = #{},
            db:execute(?DeletePerfectLoverRewardSql),
            db:execute(?DeletePerfectLoverAllSql);
        [ActSubType|_] -> %% 活动已开始，从数据库获取数据
            case db:get_all(?SelectPerfectLoverAllSql) of
                [] ->
                    WeddingTimesList = [],
                    WeddingLogList = [];
                PerfectLoverSqlList ->
                    F = fun(PLSqlInfo, {WeddingTimesList1, WeddingLogList1}) ->
                        [RoleIdM, RoleIdW, WeddingType, Time] = PLSqlInfo,
                        {IfRewardM, WeddingTimesList2} = lib_perfect_lover:update_perfect_times_info(RoleIdM, RoleIdW, WeddingType, WeddingTimesList1),
                        {IfRewardW, WeddingTimesList3} = lib_perfect_lover:update_perfect_times_info(RoleIdW, RoleIdM, WeddingType, WeddingTimesList2),
                        if
                            IfRewardM =:= true andalso IfRewardW =:= true ->
                                WeddingLogList2 = [{RoleIdM, RoleIdW, Time}|WeddingLogList1];
                            IfRewardM =:= true ->
                                WeddingLogList2 = [{RoleIdM, RoleIdW, Time}|WeddingLogList1];
                            IfRewardW =:= true ->
                                WeddingLogList2 = [{RoleIdM, RoleIdW, Time}|WeddingLogList1];
                            true ->
                                WeddingLogList2 = WeddingLogList1
                        end,
                        {WeddingTimesList3, WeddingLogList2}
                    end,
                    {WeddingTimesList, WeddingLogList} = lists:foldl(F, {[], []}, PerfectLoverSqlList)
            end,
            case db:get_all(?SelectPerfectLoverRewardSql) of
                [] ->
                    RewardState = #{};
                RewardStateList ->
                    F2 = fun([RoleId, RoleRewardState], AccMaps) ->
                        RoleRewardState2 = util:bitstring_to_term(RoleRewardState),
                        maps:put(RoleId, RoleRewardState2, AccMaps)
                    end,
                    RewardState = lists:foldl(F2, #{}, RewardStateList)
            end
    end,
    State = #perfect_lover_state{
        act_subtype = ActSubType,
        wedding_times_list = WeddingTimesList,
        wedding_log_list = WeddingLogList,
        reward_state = RewardState
    },
    {ok, State}.

handle_call(Request, From, State) ->
    case catch do_handle_call(Request, From, State) of
        {'EXIT', _Reason} ->
            ?ERR("~p ~p _Reason:~p~n", [?MODULE, ?LINE, _Reason]),
            {reply, ok, State};
        Result ->
            Result
    end.

do_handle_call(_Request, _From, State) ->
    {reply, ok, State}.

handle_cast(Info, State) ->
    case catch do_handle_cast(Info, State) of
        {'EXIT', _Reason} ->
            ?ERR("~p ~p _Reason:~p~n", [?MODULE, ?LINE, _Reason]),
            {noreply, State};
        Res ->
            Res
    end.

do_handle_cast({act_start, ActSubType}, State) ->
    #perfect_lover_state{
        act_subtype = ActSubType1
    } = State,
    case ActSubType1 of
        0 ->
            NewState = #perfect_lover_state{
                act_subtype = ActSubType
            };
        _ ->
            NewState = State
    end,
    {noreply, NewState};

do_handle_cast({act_close, ActSubType}, State) ->
    #perfect_lover_state{
        act_subtype = ActSubType1
    } = State,
    case ActSubType of
        ActSubType1 ->
            NewState = #perfect_lover_state{},
            db:execute(?DeletePerfectLoverAllSql);
        _ ->
            NewState = State
    end,
    {noreply, NewState};

do_handle_cast({add_wedding_times, RoleIdM, RoleIdW, WeddingType}, State) ->
    #perfect_lover_state{
        act_subtype = ActSubType,
        wedding_times_list = OldWeddingTimesList,
        wedding_log_list = OldWeddingLogList,
        reward_state = RewardStateMap
    } = State,
    case ActSubType of
        0 ->
            NewState = State;
        _ ->
            NowTime = utime:unixtime(),
            {IfRewardM, NewWeddingTimesList1} = lib_perfect_lover:update_perfect_times_info(RoleIdM, RoleIdW, WeddingType, OldWeddingTimesList),
            {IfRewardW, NewWeddingTimesList} = lib_perfect_lover:update_perfect_times_info(RoleIdW, RoleIdM, WeddingType, NewWeddingTimesList1),
            lib_perfect_lover:sql_perfect_lover(RoleIdM, RoleIdW, WeddingType, NowTime),
            {reward, RewardList} = lib_custom_act_util:keyfind_act_condition(?CUSTOM_ACT_TYPE_PERFECT_LOVER, ActSubType, reward),
            if
                IfRewardM =:= true andalso IfRewardW =:= true ->
                    NewWeddingLogList = [{RoleIdM, RoleIdW, NowTime}|OldWeddingLogList],
                    lib_offline_api:apply_cast(lib_perfect_lover, pl_send_mail, [RoleIdM, RoleIdW, RewardList]),
                    lib_offline_api:apply_cast(lib_perfect_lover, pl_send_mail, [RoleIdW, RoleIdM, RewardList]);
                IfRewardM =:= true ->
                    NewWeddingLogList = [{RoleIdM, RoleIdW, NowTime}|OldWeddingLogList],
                    lib_offline_api:apply_cast(lib_perfect_lover, pl_send_mail, [RoleIdM, RoleIdW, RewardList]);
                IfRewardW =:= true ->
                    NewWeddingLogList = [{RoleIdM, RoleIdW, NowTime}|OldWeddingLogList],
                    lib_offline_api:apply_cast(lib_perfect_lover, pl_send_mail, [RoleIdW, RoleIdM, RewardList]);
                true ->
                    NewWeddingLogList = OldWeddingLogList
            end,
            %% 更新奖励领取状态
            TmpRewardStateMap = lib_perfect_lover:update_reward_state(RoleIdM, RewardStateMap, WeddingType, ActSubType),
            NewRewardStateMap = lib_perfect_lover:update_reward_state(RoleIdW, TmpRewardStateMap, WeddingType, ActSubType),
            NewState = State#perfect_lover_state{
                wedding_times_list = NewWeddingTimesList,
                wedding_log_list = NewWeddingLogList,
                reward_state = NewRewardStateMap
            }
    end,
    {noreply, NewState};

do_handle_cast({open_perfect_lover, SubType, RoleId, LoverRoleId, LoverName}, State) ->
    #perfect_lover_state{
        act_subtype = ActSubType,
        wedding_times_list = WeddingTimesList,
        wedding_log_list = WeddingLogList,
        reward_state = RewardStateMap
    } = State,
    case ActSubType of
        SubType ->
            case lists:keyfind(RoleId, #wedding_times_info.role_id, WeddingTimesList) of
                false ->
                    IfGetReward = 0,
                    WeddingTimesSendList = [],
                    LoverList = [];
                #wedding_times_info{lover_list = LoverList} ->
                    WeddingDIdList = data_wedding:get_wedding_designation_id_list(),
                    WeddingTypeNum = length(WeddingDIdList),
                    case lib_perfect_lover:check_wedding_times(LoverList, WeddingTypeNum) of
                        true ->
                            IfGetReward = 1;
                        false ->
                            IfGetReward = 0
                    end,
                    case lists:keyfind(LoverRoleId, #wedding_times_lover_info.lover_role_id, LoverList) of
                        false ->
                            WeddingTimesSendList = [];
                        #wedding_times_lover_info{times_list = WeddingTimesSendList} ->
                            skip
                    end
            end,
            F = fun({RoleIdM, RoleIdW, NowTime}, SelfLogList1) ->
                if
                    RoleId =:= RoleIdM andalso LoverRoleId =:= RoleIdW ->
                        [{RoleIdM, RoleIdW, NowTime}|SelfLogList1];
                    RoleId =:= RoleIdW andalso LoverRoleId =:= RoleIdM ->
                        [{RoleIdM, RoleIdW, NowTime}|SelfLogList1];
                    true ->
                        SelfLogList1
                end
            end,
            SelfLogList = lists:foldl(F, [], WeddingLogList),
            case maps:get(RoleId, RewardStateMap, false) of
                RewardStateList when is_list(RewardStateList) ->
                    skip;
                _ ->
                    RewardStateList = []
            end,
            Argrs = [SubType, RoleId, LoverRoleId, LoverName, IfGetReward, WeddingTimesSendList, WeddingLogList, SelfLogList, LoverList],
            lib_offline_api:apply_cast(lib_perfect_lover, open_perfect_lover, [Argrs, RewardStateList]);
        _ ->
            lib_server_send:send_to_uid(RoleId, pt_331, 33115, [?ERRCODE(err331_act_closed), SubType, 0, "", 0, [], [], [], []])
    end,
    {noreply, State};

do_handle_cast({send_reward, SubType, RoleId, WeddingType}, State) ->
    #perfect_lover_state{
        reward_state = RewardStateMap
    } = State,
    case maps:get(RoleId, RewardStateMap, false) of
        RewardList when is_list(RewardList) ->
            case lists:keyfind(WeddingType, 1, RewardList) of
                {WeddingType, ReceiveState} ->
                    case ReceiveState of
                        ?CAN_RECEIVE ->
                            NewState = lib_perfect_lover:send_reward(RoleId, WeddingType, SubType, State);
                        ?ALREADY_RECEIVE ->
                            NewState = State,
                            lib_server_send:send_to_uid(RoleId, pt_331, 33116, [?ERRCODE(err331_already_get_reward), SubType, WeddingType]);
                        _ ->
                            NewState = State,
                            lib_server_send:send_to_uid(RoleId, pt_331, 33116, [?ERRCODE(err331_act_can_not_get), SubType, WeddingType])
                    end;
                _ ->
                    NewState = State,
                    lib_server_send:send_to_uid(RoleId, pt_331, 33116, [?ERRCODE(err331_act_can_not_get), SubType, WeddingType])
            end;
        _ ->
            NewState = State,
            lib_server_send:send_to_uid(RoleId, pt_331, 33116, [?ERRCODE(err331_act_can_not_get), SubType, WeddingType])
    end,
    {noreply, NewState};

do_handle_cast(_Info, State) ->
    {noreply, State}.

handle_info(Info, State) ->
    case catch do_handle_info(Info, State) of
        {'EXIT', _Reason} ->
            ?ERR("~p ~p _Reason:~p~n", [?MODULE, ?LINE, _Reason]),
            {noreply, State};
        Res ->
            Res
    end.

do_handle_info(_Info, State) ->
    {noreply, State}.

terminate(_Reason, _State) -> ok.

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