% Licensed under the Apache License, Version 2.0 (the "License"); you may not
% use this file except in compliance with the License. You may obtain a copy of
% the License at
%
%   http://www.apache.org/licenses/LICENSE-2.0
%
% Unless required by applicable law or agreed to in writing, software
% distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
% WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
% License for the specific language governing permissions and limitations under
% the License.

-module(couch_event_listener_mfa).
-behavior(couch_event_listener).

-export([
    start_link/4,
    enter_loop/4,
    stop/1
]).

-export([
    init/1,
    terminate/2,
    handle_event/3,
    handle_cast/2,
    handle_info/2
]).

-record(st, {
    mod,
    func,
    state,
    parent
}).

start_link(Mod, Func, State, Options) ->
    Parent =
        case proplists:get_value(parent, Options) of
            P when is_pid(P) -> P;
            _ -> self()
        end,
    Arg = {Parent, Mod, Func, State},
    couch_event_listener:start_link(?MODULE, Arg, Options).

enter_loop(Mod, Func, State, Options) ->
    Parent =
        case proplists:get_value(parent, Options) of
            P when is_pid(P) ->
                erlang:monitor(process, P),
                P;
            _ ->
                undefined
        end,
    St = #st{
        mod = Mod,
        func = Func,
        state = State,
        parent = Parent
    },
    couch_event_listener:enter_loop(?MODULE, St, Options).

stop(Pid) ->
    couch_event_listener:cast(Pid, shutdown).

init({Parent, Mod, Func, State}) ->
    erlang:monitor(process, Parent),
    {ok, #st{
        mod = Mod,
        func = Func,
        state = State,
        parent = Parent
    }}.

terminate(_Reason, _MFA) ->
    ok.

handle_event(DbName, Event, #st{mod = Mod, func = Func, state = State} = St) ->
    try
        case Mod:Func(DbName, Event, State) of
            {ok, NewState} ->
                {ok, St#st{state = NewState}};
            stop ->
                {stop, normal, St};
            Else ->
                couch_log:error("~p: else in handle_event for db ~p, event ~p, else ~p", [?MODULE, DbName, Event, Else]),
                erlang:error(Else)
        end
    catch
        error:Reason:Stack ->
            couch_log:error("~p: error in handle_event for db ~p, event ~p, reason ~p, stack ~p", [?MODULE, DbName, Event, Reason, Stack]),
            erlang:error(Reason);
        exit:Reason:Stack ->
            couch_log:error("~p: exit in handle_event for db ~p, event ~p, reason ~p, stack ~p", [?MODULE, DbName, Event, Reason, Stack]),
            erlang:exit(Reason);
        throw:Reason:Stack ->
            couch_log:error("~p: throw in handle_event for db ~p, event ~p, reason ~p, stack ~p", [?MODULE, DbName, Event, Reason, Stack]),
            erlang:throw(Reason)
    end.

handle_cast(shutdown, St) ->
    {stop, normal, St};
handle_cast(_Msg, St) ->
    {ok, St}.

handle_info({'DOWN', _Ref, process, Parent, _Reason}, #st{parent = Parent} = St) ->
    {stop, normal, St};
handle_info(_Msg, St) ->
    {ok, St}.
