-module(my_callbacks_correct).
-export([
callback_init/1
, callback_call/3
, callback_cast/3
, callback_exit/1
]).
-record(state, {
parent :: pid(),
status = init :: 'init' | 'open' | 'closed',
subscribe = [] :: list({pid(), integer()}),
counter = 1 :: integer()
}).
-type state() :: #state{}.
-type cast_message() :: 'open' | 'closed'.
-type call_message() :: 'subscribe' | 'unsubscribe'.
-type call_reply() :: 'accepted' | 'rejected'.
-spec callback_init(Parent::pid()) -> {'ok', state()}.
callback_init(Parent) ->
{ok, #state{parent = Parent}}.
-spec callback_cast(state(), pid(), cast_message()) -> {'noreply', state()}.
callback_cast(#state{parent = Pid} = State, Pid, Message)
when Message =:= 'open'; Message =:= 'close' ->
{noreply, State#state{status = Message}};
callback_cast(State, _Pid, _Message) ->
{noreply, State}.
-spec callback_call(state(), pid(), call_message()) ->
{'reply', state(), call_reply()}.
callback_call(#state{status = open, subscribe = Subscribers} = State,
Pid, Message)
when Message =:= 'subscribe';
Message =:= 'unsubscribe' ->
NewState =
case Message of
subscribe ->
N = State#state.counter,
State#state{subscribe = [{Pid, N}|Subscribers], counter = N+1};
unsubscribe ->
State#state{subscribe = lists:keydelete(Pid, 1, Subscribers)}
end,
{reply, NewState, accepted};
callback_call(State, _Pid, _Message) ->
{reply, State, rejected}.
-spec callback_exit(state()) -> 'ok'.
callback_exit(_State) ->
ok.