%% Copyright (C) 2025 by sysmocom - s.f.m.c. GmbH <info@sysmocom.de>
%% Author: Vadim Yanitskiy <vyanitskiy@sysmocom.de>
%%
%% All Rights Reserved
%%
%% SPDX-License-Identifier: MPL-2.0
%%
%% This Source Code Form is subject to the terms of the Mozilla Public
%% License, v. 2.0.  If a copy of the MPL was not distributed with this
%% file, You can obtain one at http://mozilla.org/MPL/2.0/.

-module(logger_gsmtap_h).

-moduledoc """
GSMTAP logging handler.
""".

%% Erlang/OTP versions below 27.0.0 have no 'logger_handler' behaviour
-if(?OTP_RELEASE >= 27).
-behaviour(logger_handler).
-endif.

%% logger_handler callbacks
-export([adding_handler/1,
         removing_handler/1,
         filter_config/1,
         log/2]).

-define(LADDR_DEFAULT, "0.0.0.0").
-define(RADDR_DEFAULT, "127.0.0.1").
-define(APP_NAME_DEFAULT, unknown).


%% ------------------------------------------------------------------
%% logger_handler API
%% ------------------------------------------------------------------

-spec adding_handler(logger_handler:config()) -> {ok, logger_handler:config()} |
                                                 {error, term()}.
adding_handler(Config) ->
    HConfig = maps:get(config, Config, #{}),
    LAddr = ipaddr(maps:get(loc_addr, HConfig, ?LADDR_DEFAULT)),
    RAddr = ipaddr(maps:get(rem_addr, HConfig, ?RADDR_DEFAULT)),
    AppName = app_name(maps:get(app_name, HConfig, ?APP_NAME_DEFAULT)),
    {ok, Pid} = logger_gsmtap:start(LAddr, RAddr, AppName),
    {ok, Config#{config => HConfig#{pid => Pid,
                                    loc_addr => LAddr,
                                    rem_addr => RAddr,
                                    app_name => AppName}}}.


-spec removing_handler(logger_handler:config()) -> ok.
removing_handler(#{config := #{pid := Pid}}) ->
    logger_gsmtap:stop(Pid),
    ok.


-spec filter_config(logger_handler:config()) -> logger_handler:config().
filter_config(#{config := HConfig} = Config) ->
    Config#{config => maps:without([pid], HConfig)}.


-spec log(logger:log_event(), logger_handler:config()) -> term().
log(LogEvent, #{config := #{pid := Pid}}) ->
    logger_gsmtap:log(Pid, LogEvent).


%% ------------------------------------------------------------------
%% private API
%% ------------------------------------------------------------------

-spec ipaddr(Addr0) -> Addr1
    when Addr0 :: string() | inet:ip_address(),
         Addr1 :: inet:ip_address().
ipaddr(AddrStr) when is_list(AddrStr) ->
    {ok, Addr} = inet:parse_address(AddrStr),
    Addr;

ipaddr(Addr) ->
    true = inet:is_ip_address(Addr),
    Addr.


-spec app_name(string() | atom()) -> string().
app_name(AppName) when is_list(AppName) ->
    AppName;

app_name(AppName) when is_atom(AppName) ->
    atom_to_list(AppName).


%% vim:set ts=4 sw=4 et:
