%%
%% %CopyrightBegin%
%%
%% Copyright Ericsson AB 2010-2020. All Rights Reserved.
%%
%% 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.
%%
%% %CopyrightEnd%
%%

%%
%% The diameter application callback module configured by server.erl.
%%

-module(server_cb).

-include_lib("diameter/include/diameter.hrl").

%% diameter callbacks
-export([peer_up/3,
         peer_down/3,
         pick_peer/4,
         prepare_request/3,
         prepare_retransmit/3,
         handle_answer/4,
         handle_error/4,
         handle_request/3]).

%% Raise an error on callbacks that aren't expected.
-define(ERROR, error({unexpected, ?MODULE, ?LINE})).

%% peer_up/3

peer_up(_SvcName, _Peer, State) ->
    State.

%% peer_down/3

peer_down(_SvcName, _Peer, State) ->
    State.

%% pick_peer/3

%% Don't let requests be sent, so other request callbacks shouldn't
%% happen.
pick_peer(_LocalCandidates, _RemoteCandidates, _SvcName, _State) ->
    false.

%% prepare_request/3

prepare_request(_Packet, _SvcName, _Peer) ->
    ?ERROR.

%% prepare_retransmit/3

prepare_retransmit(_Packet, _SvcName, _Peer) ->
    ?ERROR.

%% handle_answer/4

handle_answer(_Packet, _Request, _SvcName, _Peer) ->
    ?ERROR.

%% handle_error/4

handle_error(_Reason, _Request, _SvcName, _Peer) ->
    ?ERROR.

%% handle_request/3

%% ACR without decode errors.
handle_request(#diameter_packet{msg = ['ACR' | #{} = Request],
                                errors = []},
               _SvcName,
               {_, Caps}) ->
    #diameter_caps{origin_host = {OH,_},
                   origin_realm = {OR,_}}
        = Caps,

    #{'Session-Id' := Sid,
      'Accounting-Record-Type' := T,
      'Accounting-Record-Number' := N}
        = Request,

    Answer = #{'Result-Code' => 2001,  %% DIAMETER_SUCCESS
               'Origin-Host' => OH,
               'Origin-Realm' => OR,
               'Session-Id' => Sid,
               'Accounting-Record-Type' => T,
               'Accounting-Record-Number' => N},

    {reply, ['ACA' | Answer]};

%% ACR with decode errors.
handle_request(#diameter_packet{msg = ['ACR' | #{} = Request]},
               _SvcName,
               {_, Caps}) ->
    #diameter_caps{origin_host = {OH,_},
                   origin_realm = {OR,_}}
        = Caps,

    Answer = maps:merge(maps:with(['Session-Id'], Request),
                        #{'Origin-Host' => OH,
                          'Origin-Realm' => OR}),

    %% Let diameter set Result-Code and Failed-AVP if there were
    %% decode errors.
    {reply, ['answer-message' | Answer]};

%% Answer anything else as unsupported.
handle_request(#diameter_packet{}, _SvcName, _) ->
    {answer_message, 3001}.  %% DIAMETER_COMMAND_UNSUPPORTED
