%% @copyright 2014, Takeru Ohta <phjgt308@gmail.com>
%%
%% @doc A Local Name Registration Facility
-module(local).

%%----------------------------------------------------------------------------------------------------------------------
%% Exported API
%%----------------------------------------------------------------------------------------------------------------------
-export([start_name_server/1]).
-export([stop_name_server/1]).
-export([which_name_servers/0]).

-export([register_name/2]).
-export([unregister_name/1]).
-export([whereis_name/1]).
-export([send/2]).
-export([which_processes/1, which_processes/2]).

-export([name_server_child_spec/1, name_server_child_spec/3]).

-export([otp_name/1]).

-export_type([name/0]).
-export_type([name_server_name/0]).
-export_type([process_name/0]).
-export_type([otp_name/0]).
-export_type([otp_ref/0]).

%%----------------------------------------------------------------------------------------------------------------------
%% Macros & Types
%%----------------------------------------------------------------------------------------------------------------------
-type name() :: {name_server_name(), process_name()}.
-type name_server_name() :: atom().
-type process_name() :: term().

-type otp_name() :: {local, Name :: atom()}
                  | {global, Name :: term()}
                  | {via, module(), Name :: term()}.

-type otp_ref() :: (Name :: atom())
                 | {Name :: atom(), node()}
                 | {global, Name :: term()}
                 | {via, module(), Name :: term()}
                 | pid().

%%----------------------------------------------------------------------------------------------------------------------
%% Exported Functions
%%----------------------------------------------------------------------------------------------------------------------
%% @doc Starts a name server process
%%
%% The process is registered locally as `ServerName' using `register/2'.
%%
%% If the process is successfully started the function returns `ok'.
%%
%% If there already exists a process with the specified `ServerName' the function returnes `{error, already_present}'.
-spec start_name_server(name_server_name()) -> ok | {error, Reason} when
      Reason :: already_present.
start_name_server(ServerName) when is_atom(ServerName) ->
    local_sup:start_name_server(ServerName);
start_name_server(ServerName) -> error(badarg, [ServerName]).

%% @doc Stops the name server `ServerName'
%%
%% If successful, the function returns `ok'.
%% If the name server identified by `ServerName' does not exist, the function returns `{error, not_found}'.
-spec stop_name_server(name_server_name()) -> ok | {error, Reason} when
      Reason :: not_found.
stop_name_server(ServerName) when is_atom(ServerName) ->
    local_sup:stop_name_server(ServerName);
stop_name_server(ServerName) -> error(badarg, [ServerName]).

%% @doc Returns a list of running name server
-spec which_name_servers() -> [name_server_name()].
which_name_servers() ->
    local_sup:which_name_servers().

%% @doc Locally assocates the name `Name' with a pid `Pid'.
%%
%% Let `NameServer' is `element(1, Name)', the registered name is limited to the name server `NameServer' scope.
%%
%% Assumes that the name server is already started, crashes otherwise.
%%
%% The function returns `yes' if successful, `no' if it failes.
%% For example, `no' is returned if an attempt is made to register an already registered process or
%% to register a process with a name that is already in use.
-spec register_name(Name :: name(), Pid :: pid()) -> yes | no.
register_name({NameServer, ProcName}, Pid) when is_atom(NameServer), is_pid(Pid) ->
    local_name_server:register_name(NameServer, ProcName, Pid);
register_name(Name, Pid) -> error(badarg, [Name, Pid]).

%% @doc Removes the locally registered name `Name'
-spec unregister_name(Name :: name()) -> ok.
unregister_name({NameServer, ProcName}) when is_atom(NameServer) ->
    local_name_server:unregister_name(NameServer, ProcName);
unregister_name(Name) -> error(badarg, [Name]).

%% @doc Returns the pid with the locally registered name `Name'
%%
%% Returns `undefined' if the name is not locally registered.
-spec whereis_name(name()) -> pid() | undefined.
whereis_name({NameServer, ProcName}) when is_atom(NameServer) ->
    local_name_server:whereis_name(NameServer, ProcName);
whereis_name(Name) -> error(badarg, [Name]).

%% @doc Sends the message `Msg' to the pid locally registered as `Name'
%%
%% Failure: If `Name' is not a locally registered name, the calling function will exit with reason `{badarg, {Name, Msg}}'
-spec send(name(), term()) -> pid().
send(Name, Msg) ->
    case whereis_name(Name) of
        undefined -> error({badarg, {Name, Msg}});
        Pid       -> _ = Pid ! Msg, Pid
    end.

%% @doc Returns a list of registered process
-spec which_processes(name_server_name()) -> [{process_name(), pid()}].
which_processes(NameServer) ->
    local_name_server:which_processes(NameServer).

%% @doc Returns a list of registered process that has a name which matches the pattern `Pattern'
-spec which_processes(name_server_name(), ets:match_pattern()) -> [{process_name(), pid()}].
which_processes(NameServer, ProcNamePattern) ->
    local_name_server:which_processes(NameServer, ProcNamePattern).

%% @equiv name_server_child_spec(Name, Name, 5000)
-spec name_server_child_spec(name_server_name()) -> supervisor:child_spec().
name_server_child_spec(Name) ->
    name_server_child_spec(Name, Name, 5000).

%% @doc Returns the child spec for a local name server that is used in embedded mode.
%%
%% To embed a local name server in your application, you can simply add `ChildSpec' to your supervision tree.
-spec name_server_child_spec(ChildId, ServerName, Shutdown) -> ChildSpec when
      ChildId    :: term(),
      ServerName :: name_server_name(),
      Shutdown   :: brutal_kill | timeout(),
      ChildSpec  :: supervisor:child_spec().
name_server_child_spec(ChildId, ServerName, Shutdown) when is_atom(ServerName) ->
    {ChildId, {local_name_server, start_link, [ServerName]}, permanent, Shutdown, worker, [local_name_server]};
name_server_child_spec(ChildId, ServerName, Shutdown) ->
    error(badarg, [ChildId, ServerName, Shutdown]).

%% @doc Returns OTP compatible name
-spec otp_name(name()) -> otp_name().
otp_name(Name) ->
    {via, local, Name}.
