%%--------------------------------------
%%% @Module  : lib_activitycalen_api
%%% @Author  : xiaoxiang
%%% @Created : 2017-03-01
%%% @Description:  lib_activitycalen_api
%%%--------------------------------------
-module(lib_activitycalen_api).
-export([
        success_end_activity/2          %% 活动结束,用于记录活动当前状态，和活动首次开启记录
        , success_end_activity/1        %% 活动结束,用于记录活动当前状态，和活动首次开启记录
        , success_end_activity/3        %% 活动结束,用于记录活动当前状态，和活动首次开启记录
        , success_start_activity/3      %% 活动开启,用于记录活动当前状态，和活动首次开启记录
        , success_start_activity/2      %% 活动开启,用于记录活动当前状态，和活动首次开启记录
        , success_start_activity/1      %% 活动开启,用于记录活动当前状态，和活动首次开启记录
        % , ps_success_end_activity/3     %% 玩家完成活动用于记录玩家活跃度   ps
        % , ps_success_end_activity/2     %% 玩家完成活动用于记录玩家活跃度   ps
        , get_time/2                    %% 查询活动的当日的活动时间
        , get_time/1                    %% 查询活动的当日的活动时间
        , check_ac_start/1              %% 检查活动是否符合开启条件
        , check_ac_start/2              %% 检查活动是否符合开启条件
        , check_ac_start/3              %% 检测某天活动是否开启
        , check_ac_start/4              %% 检测某天玩家是否能参加该活动
        , check_mod_ac_start/3          %% 检查活动是否符合开启条件
        , role_success_end_activity/3   %% 玩家完成活动用于记录玩家活跃度
        , role_success_end_activity/4   %% 玩家完成活动用于记录玩家活跃度
        % , add_power_live/4              %% 增加活力
        , cost_power_live/4             %% 扣除活力
        , get_live_ness/3               %% 获取玩家每日活跃度
        , calc_continue_time/2          %% 计算活动持续时间
        , calc_continue_time/3          %% 计算活动持续时间
        , get_ac_end_time/4             %% 计算活动结束时间
        , coin_get_event/2              %% 交易券获得
        , honour_get_event/2            %% 名望券获得
    ]).
-compile(export_all).
-include("server.hrl").
-include("figure.hrl").
-include("errcode.hrl").
-include("activitycalen.hrl").
-include("predefine.hrl").
-include("common.hrl").
-include("def_daily.hrl").
-include("dungeon.hrl").
-include("def_module.hrl").
-include("def_goods.hrl").
-include_lib("stdlib/include/ms_transform.hrl").

%%%-------------------------
% 活动开启和活动结束用于记录活动当前状态，和活动首次开启记录
%%%---------------------------
%% return ok
%% 活动结束 定时活动调用
success_end_activity(Module) ->
    success_end_activity(Module, 0).
success_end_activity(Module, ModuleSub) ->
    AcSub = lib_activitycalen:get_ac_sub_with_end(Module, ModuleSub),
   success_end_activity(Module, ModuleSub, AcSub).
success_end_activity(Module, ModuleSub, AcSub) ->
    mod_activitycalen:success_end_activity(Module, ModuleSub, AcSub).
%% return ok
%% 活动开启 定时活动调用
success_start_activity(Module) ->
    success_start_activity(Module, 0).
success_start_activity(Module, ModuleSub) ->
    AcSub = lib_activitycalen:get_ac_sub_with_end(Module, ModuleSub),
    success_start_activity(Module, ModuleSub, AcSub).
success_start_activity(Module, ModuleSub, AcSub) ->
    mod_activitycalen:success_start_activity(Module, ModuleSub, AcSub).


%% -------------------------------------
% 玩家完成活动用于记录玩家活跃度
%% -------------------------------------
%% 玩家完成活动


%% -------------------------------------
% 玩家完成活动用于记录玩家活跃度
%% -------------------------------------
%% role_id return ok
%% ps return #player_status{}
%% 玩家完成活动
role_success_end_activity(RoleId, Module, ModuleSub) when is_integer(RoleId )->
    role_success_end_activity(RoleId, Module, ModuleSub, 1);

role_success_end_activity(Player, Module, ModuleSub) when is_record(Player, player_status)->
    role_success_end_activity(Player, Module, ModuleSub, 1).



%% Count 完成次数
role_success_end_activity(RoleId, Module, ModuleSub, Count) when is_integer(RoleId ) ->
    case misc:is_process_alive(misc:get_player_process(RoleId)) of
        true ->
            lib_player:apply_cast(RoleId, ?APPLY_CAST_STATUS, lib_activitycalen, role_success_end_activity, [Module, ModuleSub, Count]);
        _ ->
            lib_activitycalen:role_success_end_activity_offline(RoleId, Module, ModuleSub, Count)
    end,
    ok;
role_success_end_activity(Player, Module, ModuleSub, Count) when is_record(Player, player_status) ->
    lib_activitycalen:role_success_end_activity(Player, Module, ModuleSub, Count).
%% ----------------------------------------------
%% 查询活动的当日的活动时间
%%----------------------------------------------
% return [{start_hour,start_min}|...] || []
get_time(Module) ->
    get_time(Module, 0).
get_time(Module, ModuleSub) ->
    lib_activitycalen:get_time(Module, ModuleSub).

%% ----------------------------------------------
%% 检查活动是否符合开启条件
%%----------------------------------------------
% return true|false
check_ac_start(Module) ->
    check_ac_start(Module, 0).
check_ac_start(Module, ModuleSub) ->
    lib_activitycalen:check_ac_start(Module, ModuleSub).

check_mod_ac_start(Module, ModuleSub,Act)->
    lib_activitycalen:check_mod_ac_start(Module, ModuleSub,Act).


%% 查询活动当天是否开启是否开启
%%　DataTime:{{Year, Month, Day},{Hour, Min, Sec}}
%% return [ac_sub|...]  | []
check_ac_start(Module, ModuleSub, DataTime) ->
    lib_activitycalen_check:check_ac_start(Module, ModuleSub, DataTime).

check_ac_start(Player, Module, ModuleSub, DataTime) ->
    #player_status{figure = #figure{lv = Lv}} = Player,
    AcSubList = lib_activitycalen_check:check_ac_start(Module, ModuleSub, DataTime),
    List = [1||AcSub<-AcSubList, case data_activitycalen:get_ac(Module, ModuleSub, AcSub) of
                            #base_ac{start_lv = StartLv, end_lv = EndLv} when StartLv=<Lv andalso Lv=<EndLv ->
                                true;
                            _ ->
                                false
                        end],

    lists:member(1, List).


%% 获取首个开启中的活动
get_first_enabled_ac_id(Module, ModuleSub) ->
    IdList = data_activitycalen:get_ac_sub(Module, ModuleSub),
    CheckList = [time, time_region, week, month, open_day, merge_day],
    get_first_enabled_ac_id(Module, ModuleSub, IdList, CheckList).

get_first_enabled_ac_id(Module, ModuleSub, [Id|T], CheckList) ->
    case lib_activitycalen_util:do_check_ac_sub(data_activitycalen:get_ac(Module, ModuleSub, Id), CheckList) of
        true ->
            {ok, Id};
        _ ->
            get_first_enabled_ac_id(Module, ModuleSub, T, CheckList)
    end;
get_first_enabled_ac_id(_, _, [], _) -> error.

is_enabled(Module, ModuleSub, ActId) ->
    CheckList = [time, time_region, week, month, open_day, merge_day],
    lib_activitycalen_util:do_check_ac_sub(data_activitycalen:get_ac(Module, ModuleSub, ActId), CheckList).

%% ---------------------------------------------------------------------------
%% @doc 活力增加
% -spec add_power_live(PS, AddLive, Module, Type) ->  Return when
%     PS             :: #player_status{},         %% #player_status{}
%     AddLive        :: integer(),                %% 增加活力值
%     Module         :: integer(),                %% 功能模块id
%     Type           :: integer(),                %% 消耗类型（功能自定义）
%     Return         :: ok|{false, integer()}.    %% 返回：ok|{false,错误码}
% %% ---------------------------------------------------------------------------
% add_power_live(PS, AddLive, Module, Type) ->
%     #player_status{id = RoleId, figure = #figure{lv = Lv}} = PS,
%     case lib_activitycalen:add_power_live(RoleId, Lv, AddLive, Module, Type) of
%         ok -> ok;
%         false -> {false, ?ERRCODE(err157_power_live_limit)}
%     end.

%% ---------------------------------------------------------------------------
%% @doc 活力扣除
-spec cost_power_live(PS, CostLive, Module, Type) -> Return when
    PS             :: #player_status{},         %% #player_status{}
    CostLive        :: integer(),               %% 消耗活力值
    Module         :: integer(),                %% 功能模块id
    Type           :: integer(),                %% 消耗类型（功能自定义）
    Return         :: ok|{false, integer()}.    %% 返回：ok|{false,错误码}
%% ---------------------------------------------------------------------------
cost_power_live(PS, CostLive, Module, Type) ->
    RoleId = PS#player_status.id,
    OldLive = lib_counter:get_count(RoleId, ?MOD_ACTIVITY, ?POWER_LIVE_DAILY),
    case OldLive >= CostLive of
        true ->
            CostB = lists:concat(["-", CostLive]),
            lib_log_api:log_power_live(RoleId, Module, Type, OldLive, CostB, OldLive - CostLive),
            lib_counter:set_count(RoleId, ?MOD_ACTIVITY, ?POWER_LIVE_DAILY, max(0, OldLive - CostLive) ),
            ok;
        false -> {false, ?ERRCODE(err157_power_live_limit)}
    end.

%% ---------------------------------------------------------------------------
%% @doc 获取玩家每日活跃度(只保留了5天)
-spec get_live_ness(PS, StTime, EtTime) -> Return when
    PS             :: #player_status{},                             %% #player_status{}
    StTime         :: integer(),                                    %% 开始时间
    EtTime         :: integer(),                                    %% 结束时间
    Return         :: [{Time::integer(), LiveNess::integer()}].     %% Time:零点时间, LiveNess:活跃度值
%% ---------------------------------------------------------------------------
get_live_ness(PS, StTime, EtTime) ->
    #player_status{id = RoleId} = PS,
    case ets:lookup(?ETS_ACTIVITYCALEN, RoleId) of
        [#ets_activitycalen{liveness_list = LiveNessList}] ->
            [ {Time, Val} || {Time, Val} <- LiveNessList, Time >= StTime, Time =< EtTime];
        _ ->
            []
    end.


%%副本完成
finish_dungeon(RoleID, Mod, DunType, DunID)->
    finish_dungeon(RoleID, Mod, DunType, DunID, 1).

finish_dungeon(RoleID, Mod, DunType, DunID, Count) ->
    case DunType of
        ?DUNGEON_TYPE_MATERIAL->
            role_success_end_activity(RoleID, Mod, DunID);
        ?DUNGEON_TYPE_EXP->
            role_success_end_activity(RoleID, Mod, DunID);
        ?DUNGEON_TYPE_GUARD ->
            role_success_end_activity(RoleID, 215, 2);
        ?DUNGEON_TYPE_PET->
            role_success_end_activity(RoleID, Mod, DunType);
        ?DUNGEON_TYPE_TOWER->
            role_success_end_activity(RoleID, Mod, DunType);
        ?DUNGEON_TYPE_VISUS->
            role_success_end_activity(RoleID, Mod, DunType);
        ?DUNGEON_TYPE_GOD->
            role_success_end_activity(RoleID, Mod, DunType);
        ?DUNGEON_TYPE_PER_BOSS->
            role_success_end_activity(RoleID, ?MOD_LOCAL_BOSS, 1, Count);
        _->
            DunType
    end.

success_finish_dungeon(RoleID, _Mod, DunType, _DunID)->
    success_finish_dungeon(RoleID, _Mod, DunType, _DunID, 1).

success_finish_dungeon(RoleID, _Mod, DunType, _DunID, Count) ->
    case DunType of
        ?DUNGEON_TYPE_CRUSADE->
            role_success_end_activity(RoleID, 215, 1, Count);
        ?DUNGEON_TYPE_MAIN_LINE ->
            role_success_end_activity(RoleID, 610, DunType);
        _->
            DunType
    end.

calc_continue_time(Mod,Act)->
    calc_continue_time(Mod,1,Act).
calc_continue_time(Mod,SubMod,Act)->
    case data_activitycalen:get_ac(Mod,SubMod,Act) of
        #base_ac{time_region = [{{StartH,StartM},{StartH,EndM}}|_]}->
            (EndM-StartM)*60;
        #base_ac{time_region = [{{StartH,StartM},{EndH,EndM}}|_]}->
            ((EndH-StartH-1)*60+EndM+60-StartM)*60;
        _->
            0
    end.

%% 获取活动结束时间
get_ac_end_time(Module, ModuleSub, AcSub, Now)->
    case data_activitycalen:get_ac(Module, ModuleSub, AcSub) of
        #base_ac{time_region = TimeRegion} when is_list(TimeRegion) andalso TimeRegion=/=[]->
            get_end_time(TimeRegion, hd(TimeRegion), erlang:date(), Now);
        _ -> Now + 20*60
    end.
get_end_time([], {{SH, SN}, {EH, EN}}, _Date, Now) ->
    Time = (EH*3600 + EN*60) - (SH*3600 + SN*60),
    Now + Time;
get_end_time([], _, _Date, Now) -> %%兼容策划时间配错
    ?ERR("get_end_time~n",[]),
    Now + 20*60;
get_end_time([{{SH, SN}, {EH, EN}}|T], Hd, Date, Now) ->
    St = utime:unixtime({Date, {SH, SN, 0}}),
    Et = utime:unixtime({Date, {EH, EN, 0}}),
    case Now>= St andalso Now=<Et of
        true-> Et;
        false-> get_end_time(T, Hd, Date, Now)
    end;
get_end_time([_ |T], Hd, Date, Now) ->
    get_end_time(T, Hd, Date, Now).


%%交易券获得
coin_get_event(Status, Amount)->
    #player_status{id=RoleID}=Status,
    TCoin = lib_daily:get_count(RoleID,?MOD_ACTIVITY, ?ACTIVITY_COIN_DAILY),
    Limit = lib_daily:get_count_limit(?MOD_ACTIVITY, ?ACTIVITY_COIN_DAILY),
    NCoin = min(TCoin+Amount,Limit),
    case TCoin<Limit of
        true when NCoin>=Limit->
            {ok,Bin} = pt_157:write(15716,[?TYPE_COIN,NCoin]),
            lib_server_send:send_to_uid(RoleID,Bin),
            lib_daily:set_count(RoleID,?MOD_ACTIVITY, ?ACTIVITY_COIN_DAILY,NCoin),
            role_success_end_activity(RoleID, ?MOD_PLAYER, 5);
        true ->
            {ok,Bin} = pt_157:write(15716,[?TYPE_COIN,NCoin]),
            lib_server_send:send_to_uid(RoleID,Bin),
            lib_daily:set_count(RoleID,?MOD_ACTIVITY, ?ACTIVITY_COIN_DAILY,NCoin);
        _->
            skip
    end.


%%名望券获得
honour_get_event(Status, Amount)->
    #player_status{id=RoleID}=Status,
    THonour = lib_daily:get_count(RoleID,?MOD_ACTIVITY, ?ACTIVITY_HONOUR_DAILY),
    Limit = lib_daily:get_count_limit(?MOD_ACTIVITY, ?ACTIVITY_HONOUR_DAILY),
    NHonour = min(THonour+Amount,Limit),
    case THonour<Limit of
        true when NHonour>=Limit->
            {ok,Bin} = pt_157:write(15716,[?TYPE_HONOUR,NHonour]),
            lib_server_send:send_to_uid(RoleID,Bin),
            lib_daily:set_count(RoleID,?MOD_ACTIVITY, ?ACTIVITY_HONOUR_DAILY,NHonour),
            role_success_end_activity(RoleID, ?MOD_PLAYER, 6);
        true ->
            {ok,Bin} = pt_157:write(15716,[?TYPE_HONOUR,NHonour]),
            lib_server_send:send_to_uid(RoleID,Bin),
            lib_daily:set_count(RoleID,?MOD_ACTIVITY, ?ACTIVITY_HONOUR_DAILY,NHonour);
        _->
            skip
    end.

%% -------------------------------------------------------------
%% @doc 活动进入状态的记录和清理
%% 使用ets表进行记录，key为活动协议号
%% 1. 每个调用此方法记录的活动必须在 activity_module 下添加活动协议号
%% 2. 玩家进入活动调用   ?MODULE:enter_activity_record/3      进行记录
%% 3. 活动进入状态调用   ?MODULE:get_enter_activity_record/2  进行获取
%% 4. 活动结束后调用     ?MODULE:activity_end_clean_record/1  进行清理
%% @end
activity_module(Module) ->
    ActivityList = [
        ?MOD_GUILD_BOSS,
        ?MOD_GUILD_COLLECT,
        ?MOD_GUILD,
        ?MOD_WASTELAND_WAR,
        ?MOD_BEACH
    ],
    lists:member(Module, ActivityList).

%% @doc 进入活动记录进入状态
%% @param:
%% Module:     活动模块Id
%% CountDown:  1 - 倒计时结束进入 0 - 非倒计时结束进入
%% @end
enter_activity_record(Module, RoleId, CountDown) when CountDown == 0 orelse CountDown == 1->
    case activity_module(Module) of
        true ->
            case ets:lookup(?ETS_ACTIVITY_IN_STATE, {Module, RoleId}) of
                [#ets_activity_in_state{}|_] ->
                    ignore;
                _ ->
                    NewEtsInfo = #ets_activity_in_state{
                       key = {Module, RoleId}, mod_id = Module, is_count_down = CountDown
                    },
                    ets:insert(?ETS_ACTIVITY_IN_STATE, NewEtsInfo)
            end;
        _ ->
            ignore
    end;
enter_activity_record(_Module, _RoleId, _CountDown) ->
    ignore.

%% @doc
%% 获取活动进入状态记录
%% return : 0/1
%% @end
get_enter_activity_record(Module, RoleId) ->
    case ets:lookup(?ETS_ACTIVITY_IN_STATE, {Module, RoleId}) of
        [#ets_activity_in_state{is_count_down = CountDown}|_] ->
            CountDown;
        _ ->
            CountDown = 0
    end,
    CountDown.

%% @doc
%% 活动结束清理活动记录
%% @end
activity_end_clean_record(Module, DelayTime) ->
    spawn(fun() -> timer:sleep(DelayTime * 1000), activity_end_clean_record_core(Module)  end),
    ok.

activity_end_clean_record_core(Module) ->
    case activity_module(Module) of
        true ->
            MatchSpecDel = ets:fun2ms(
                fun(#ets_activity_in_state{mod_id = ModId} = EtsInfo) when ModId =:= Module -> EtsInfo end
            ),
            EtsInfos = ets:select(?ETS_ACTIVITY_IN_STATE, MatchSpecDel),
            F = fun(TEtsInfo) ->
                ets:delete_object(?ETS_ACTIVITY_IN_STATE, TEtsInfo)
                end,
            lists:map(F, EtsInfos),
            ok;
        _ ->
            ignore
    end.
