%%-----------------------------------------------------------------------------
%% @Module  :       lib_player_check.erl
%% @Author  :       J
%% @Email   :       j-som@foxmail.com
%% @Created :       2017-11-20
%% @Description:    条件检查
%%-----------------------------------------------------------------------------
-module (lib_player_check).
-include ("errcode.hrl").
-include ("scene.hrl").
-include ("server.hrl").
-include ("attr.hrl").

-export ([check_all/1, check_list/2, check/2]).

-export ([send_error_to_sid/2, send_error_to_uid/2]).

%% return true | {false, Code}
check_all(Player) ->
    check_list(Player, [alive, action_free, safe_scene, is_transferable, dun_multi_match]).

%% return true | {false, Code}
check_list(Player, [H|T]) ->
    case check(Player, H) of
        true ->
            check_list(Player, T);
        Error ->
            Error
    end;

check_list(_Player, []) -> true.


check(Player, {'and', List}) ->
    check_list(Player, List);

check(Player, {'or', List}) ->
    case lists:any(fun
        (H) ->
            case check(Player, H) of
                true ->
                    true;
                _ ->
                    false
            end
    end, List) of
        false ->
            check(Player, hd(List));
        true ->
            true
    end;


check(Player, not_on_dungeon) ->
    case lib_dungeon:is_on_dungeon(Player) of
        true ->
            {false, ?ERRCODE(err610_had_on_dungeon)};
        _ ->
            true
    end;

check(Player, safe_scene) ->
    #player_status{scene = SceneId} = Player,
    case data_scene:get(SceneId) of
        #ets_scene{type = Type} ->
            if
                Type =:= ?SCENE_TYPE_NORMAL
                    orelse Type =:= ?SCENE_TYPE_OUTSIDE
                    orelse Type =:= ?SCENE_TYPE_GUILD ->
                    true;
                true ->
                    {false, ?ERRCODE(cannot_transferable_scene)}
            end;
        _ ->
            true
    end;

check(Player, outside) ->
    #player_status{scene = SceneId} = Player,
    case data_scene:get(SceneId) of
        #ets_scene{type = Type} ->
            if
                Type =:= ?SCENE_TYPE_NORMAL
                    orelse Type =:= ?SCENE_TYPE_OUTSIDE ->
                    true;
                true ->
                    {false, ?ERRCODE(cannot_transferable_scene)}
            end;
        _ ->
            true
    end;

check(Player, action_free) ->
    #player_status{action_lock = LockInfo} = Player,
    case LockInfo of
        free ->
            true;
        _ ->
            {false, LockInfo}
    end;

check(Player, is_transferable) ->
    case lib_scene:is_transferable(Player) of
        {true, 1} ->
            true;
        {false, Code} ->
            {false, Code};
        _ ->
            {false, ?ERRCODE(err120_cannot_transfer_scene)}
    end;

check(Player, alive) ->
    #player_status{battle_attr = #battle_attr{hp = Hp}} = Player,
    if
        Hp > 0 ->
            true;
        true ->
            {false, ?ERRCODE(player_die)}
    end;

check(Player, dun_multi_match) ->
    case lib_dun_multi:not_is_in_dun_multi_match(Player) of
        true ->
            true;
        {false, Code} ->
            {false, Code}
    end;

check(_Player, _) -> {false, ?FAIL}.


send_error_to_sid(Sid, Code) ->
    {ErrorCodeInt, ErrorCodeArgs} = util:parse_error_code(Code),
    {ok, BinData} = pt_102:write(10205, [ErrorCodeInt, ErrorCodeArgs]),
    lib_server_send:send_to_sid(Sid, BinData).

send_error_to_uid(Uid, Code) ->
    {ErrorCodeInt, ErrorCodeArgs} = util:parse_error_code(Code),
    {ok, BinData} = pt_102:write(10205, [ErrorCodeInt, ErrorCodeArgs]),
    lib_server_send:send_to_uid(Uid, BinData).