%%
%% %CopyrightBegin%
%%
%% Copyright Ericsson AB 2010-2015. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
%% compliance with the License. You should have received a copy of the
%% Erlang Public License along with this software. If not, it can be
%% retrieved online at http://www.erlang.org/.
%%
%% Software distributed under the License is distributed on an "AS IS"
%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
%% the License for the specific language governing rights and limitations
%% under the License.
%%
%% %CopyrightEnd%
%%

%%
%% The top supervisor for the diameter application.
%%

-module(diameter_sup).

-behaviour(supervisor).

%% interface
-export([start_link/0,  %% supervisor start
         tree/0]).      %% supervision tree

%% supervisor callback
-export([init/1]).

-define(CHILDREN, [diameter_misc_sup,
                   diameter_watchdog_sup,
                   diameter_peer_fsm_sup,
                   diameter_transport_sup,
                   diameter_service_sup]).

-define(TABLES, [{diameter_sequence, [set]},
                 {diameter_service,  [set, {keypos, 3}]},
                 {diameter_request,  [bag]},
                 {diameter_config,   [bag, {keypos, 2}]}]).

%% start_link/0

start_link() ->
    SupName = {local, ?MODULE},
    supervisor:start_link(SupName, ?MODULE, []).

%% init/1

init([]) ->
    ets_new(?TABLES),
    diameter_session:init(),
    Flags = {one_for_one, 1, 5},
    ChildSpecs = lists:map(fun spec/1, ?CHILDREN),
    {ok, {Flags, ChildSpecs}}.

%% spec/1

spec(Mod) ->
    {Mod,
     {Mod, start_link, []},
     permanent,
     infinity,
     supervisor,
     [Mod]}.

%% ets_new/1

ets_new(List)
  when is_list(List) ->
    lists:foreach(fun ets_new/1, List);

ets_new({Table, Opts}) ->
    ets:new(Table, [named_table, public | Opts]).

%% tree/0

tree() ->
    [{?MODULE, whereis(?MODULE), tree(?MODULE)}].

tree(Sup) ->
    lists:map(fun t/1, supervisor:which_children(Sup)).

t({Name, Pid, supervisor, _}) ->
    t(Name, Pid, tree(Pid));
t({Name, Pid, worker, _}) ->
    t(Name, Pid).

t(undefined, Pid, Children) ->
    {Pid, Children};
t(Name, Pid, Children) ->
    {Name, Pid, Children}.

t(undefined, Pid) ->
    Pid;
t(Name, Pid) ->
    {Name, Pid}.
