%%%-------------------------------------------------------------------
%%% @author liushl
%%% @doc
%%%     离线托管
%%% @end
%%%-------------------------------------------------------------------
-module(offline_hosting_api).
-author("liushl").

-include("server.hrl").
-include("common.hrl").
-include("predefine.hrl").
-include("attr.hrl").
-include("offline_hosting.hrl").
-include("role.hrl").
-include("def_module.hrl").
-include("def_event.hrl").
-include("rec_event.hrl").

%% API
-export([
    login/2,
    re_login/1,
    logout/2
    , check_add_value/2            %% 增加活跃度的时候判断增加托管值
    , handle_event/2
    , is_offline_hosting/1          %% 是否离线托管状态
    , is_offline_hosting/2          %% 是否离线托管状态
    , is_hosting_dummy/1            %% 是否假人托管状态
    , is_hosting_dummy/2            %% 是否假人托管状态
    , get_hosting_num/0             %% 获得离线托管玩家数量
    , change_scene_callback/4

    , notice_mon_hosting_end/2
    , mon_hosting_end/2
    , gm_add_value/2

]).

%% 获得离线托管人数
get_hosting_num() ->
    ets:foldl(
        fun(#ets_hosting_role{mon_id = MonId}, Num) ->
            case MonId > 0 of
                true  -> Num;
                false -> Num + 1
            end
        end, 0, ?ETS_HOSTING_ROLE
    ).

%% 四点重置
handle_event(Player, #event_callback{type_id = ?EVENT_FOUR_CLOCK}) ->
    case utime:day_of_week() of
        1 ->
            offline_hosting_data:host_setting_lookup(Player#player_status.id);
        _ ->
            ok
    end,
    {ok, Player}.

%% 是否离线托管状态
is_offline_hosting(Player) ->
    Player#player_status.online =:= ?ONLINE_OFF_HOSTING andalso
        Player#player_status.offline_hosting#offline_hosting.handler =/= undefined.

%% 是否离线托管状态
is_offline_hosting(RoleId, Mod) ->
    case offline_hosting_data:hosting_role_lookup(RoleId) of
        [#ets_hosting_role{mod = Mod}] ->
            true;
        _ ->
            false
    end.

%% 是否假人托管状态
is_hosting_dummy(RoleId, Mod) ->
    case offline_hosting_data:hosting_role_lookup(RoleId) of
        [#ets_hosting_role{mod = Mod, mon_id = MonId}] when MonId > 0 ->
            true;
        _ ->
            false
    end.

%% 是否假人托管状态
is_hosting_dummy(RoleId) ->
    case offline_hosting_data:hosting_role_lookup(RoleId) of
        [#ets_hosting_role{mon_id = MonId}] when MonId > 0 ->
            true;
        _ ->
            false
    end.

%% 登录
login(RoleId, OnlineFlag) ->
    LogData = db:get_all(io_lib:format(?HOST_LOAD_LOG, [RoleId])),
    Log = [
        #offline_hosting_log{
            key = {Module, SubId}
            , duration = Duration
            , cost_value = CostValue
            , time = Time
            , award = util:bitstring_to_term(Award)
        } || [Module, SubId, CostValue, Award, Duration, Time] <- LogData
    ],
    %% 登录事件
    case offline_hosting_data:hosting_role_lookup(RoleId) of
        [#ets_hosting_role{mod = Mod}] ->
            util:send_after([], 50, self(), {'mod', lib_player_event, dispatch, [?EVENT_HOSTING_DUMMY_LOGIN, Mod]});
        _ ->
            ignore
    end,
    OnlineFlag =:= ?ONLINE_ON andalso
        offline_hosting_data:host_setting_lookup(RoleId),
    #offline_hosting{
        log = Log
    }.

%% 托管期间，玩家重新上线: 结束当前托管
re_login(Player) ->
    #player_status{id = RoleId, offline_hosting = #offline_hosting{mod_id = Module}} = Player,
    Player1 = lib_activity_reserve:trigger_reserve_act(Player, Module, true),
    {ok, Player2} = offline_hosting:host_behavior('END', Player1, []),
    case offline_hosting_data:hosting_role_lookup(RoleId) of
        [#ets_hosting_role{mon_id = MonId, mod = Mod}] when MonId > 0 ->
            %% 假人托管中
            {ok, LastPlayer} = lib_player_event:dispatch(Player2, ?EVENT_HOSTING_DUMMY_LOGIN, Mod),
            LastPlayer;
        _ ->
            Player2
    end.

%% 托管期间离线
logout(Player, _NowTime) ->
    case is_offline_hosting(Player) of
        true  ->
            %% 托管状态下线，结束托管
            offline_hosting:host_behavior('END', Player, []);
        false ->
            ok
    end.

%% 活跃度增加时增加托管值
check_add_value(Player, Add) ->
    #player_status{
        id = RoleId
    } = Player,
    DailyGet = offline_hosting_data:host_daily_value_lookup(RoleId),
    DailyLimit = data_offline_hosting:get_offline_hosting_kv(ai_limit),
    case DailyGet >= DailyLimit of
        true  ->
            ok;
        false ->
            #ets_offline_hosting{
                value = Value
            } = Setting = offline_hosting_data:host_setting_lookup(RoleId),
            Per = data_offline_hosting:get_offline_hosting_kv(activity_to_ai),
            AddValue = Add div Per,
            FinalAdd =
                case AddValue > 0 of
                    true  ->
                        %% 新增的活跃值足够转为托管值，但是仍需判断是否剩下活跃度
                        Left = Add rem Per,
                        case Left =:= 0 of
                            true  ->
                                %% 不剩下活跃度了
                                AddValue;
                            false ->
                                %% 还剩下一些活跃度不够转化为托管值
                                %% 则需要继续判断今日累计的活跃度够不够转化
                                AddValue + check_daily_left_live(RoleId, Per, Left)
                        end;
                    false ->
                        %% 新增的不够转为，判断今日累计的活跃度够不够转化
                        check_daily_left_live(RoleId, Per, Add)
                end,
            FixAdd = min(FinalAdd, DailyLimit - DailyGet),
            case FixAdd > 0 of
                true  ->
                    NewSetting = Setting#ets_offline_hosting{value = FixAdd + Value, u_time = utime:unixtime()},
                    offline_hosting_data:host_daily_value_save(RoleId, DailyGet + FixAdd),
                    offline_hosting_data:host_save_setting(NewSetting);
                false ->
                    ok
            end
    end,
    Player.
%% 判断今日累计的活跃度够不够转化
check_daily_left_live(RoleId, Per, Left) ->
    DailyLeft = offline_hosting_data:host_daily_live_get(RoleId),
    AddDailyLeft = DailyLeft + Left,
    LeftAdd = AddDailyLeft div Per,
    case LeftAdd > 0 of
        true  ->
            FinalLeft = AddDailyLeft rem Per,
            offline_hosting_data:host_daily_live_save(RoleId, FinalLeft),
            LeftAdd;
        false ->
            offline_hosting_data:host_daily_live_save(RoleId, AddDailyLeft),
            0
    end.

%% 怪物托管结束，通知玩家
notice_mon_hosting_end(RoleId, Log) ->
    lib_player:apply_cast(RoleId, ?APPLY_CAST_STATUS, ?MODULE, mon_hosting_end, [Log]).
mon_hosting_end(Player, Log) ->
    #player_status{
        offline_hosting = Hosting
    } = Player,
    NewHosting = Hosting#offline_hosting{log = [Log|Hosting#offline_hosting.log]},
    Player#player_status{offline_hosting = NewHosting}.

%% GM加托管值
gm_add_value(Player, Add) ->
    Setting = offline_hosting_data:host_setting_lookup(Player#player_status.id),
    NewSetting = Setting#ets_offline_hosting{value = Add, u_time = utime:unixtime()},
    offline_hosting_data:host_save_setting(NewSetting),
    Player.

%% 托管玩家前往野外场景需要停止行为
change_scene_callback(Player, _, _, _) ->
    case lib_scene:is_outside_scene(Player#player_status.scene) of
        true  ->
            offline_hosting:stop_behavior(Player);
        false ->
            Player
    end.