%%
%% %CopyrightBegin%
%% 
%% Copyright Ericsson AB 2000-2009. 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%
%%

%%
%%----------------------------------------------------------------------
%% Purpose : Handle ASN.1 BER encoding of Megaco/H.248
%%----------------------------------------------------------------------

-module(megaco_binary_term_id).


%%----------------------------------------------------------------------
%% Include files
%%----------------------------------------------------------------------

-include_lib("megaco/include/megaco.hrl"). 
-include_lib("megaco/src/engine/megaco_message_internal.hrl").


%%----------------------------------------------------------------------
%% External exports
%%----------------------------------------------------------------------

-export([encode/2, decode/2]).


%%----------------------------------------------------------------------
%% Internal exports
%%----------------------------------------------------------------------


%%----------------------------------------------------------------------
%% Macros
%%----------------------------------------------------------------------

-define(default_config, [8,8,8]).

-define(asn_root_termination_id,
	#'TerminationID'{wildcard = [],
			 id       = [16#FF, 16#FF, 16#FF, 16#FF,
				     16#FF, 16#FF, 16#FF, 16#FF]}).

-define(megaco_all_wildcard_termination_id,    
	#megaco_term_id{contains_wildcards = true,
			id                 = [[?megaco_all]]}).
-define(megaco_choose_wildcard_termination_id, 
	#megaco_term_id{contains_wildcards = true,
			id                 = [[?megaco_choose]]}).


%%----------------------------------------------------------------------
%% Convert a 'TerminationId' record into a ASN.1 termination id
%% Return {ok, TermId} | {error, Reason}
%%---------------------------------------------------------------------- 

encode(_Config, TermId) when TermId =:= ?megaco_root_termination_id ->
    {ok, ?asn_root_termination_id};
encode(Config, TermId) when (TermId =:= ?megaco_all_wildcard_termination_id) andalso 
			    (Config =:= ?default_config) ->
    {ok, asn_all_tid()};
encode(Config, TermId) when (TermId =:= ?megaco_choose_wildcard_termination_id) andalso 
                            (Config =:= ?default_config)  ->
    {ok, asn_choose_tid()};
encode(Config, #megaco_term_id{contains_wildcards = false, id = IDs}) ->
    case (catch encode1(IDs,Config)) of
	{'EXIT',Reason} ->
	    {error,Reason};
	EncodedTid ->
	    {ok, EncodedTid}
    end;
encode(Config, #megaco_term_id{contains_wildcards = true, id = IDs}) ->
    case (catch encode2(IDs,Config)) of
	{'EXIT',Reason} ->
	    {error,Reason};
	EncodedTid ->
	    {ok, EncodedTid}
    end;
encode(_Config, TermId) ->
    {error, {bad_type, TermId}}.


first_bit() -> 
    lists:sum(?default_config) - 1.
asn_all_tid() -> 
    #'TerminationID'{wildcard = [[(2#11000000 + first_bit())]],
		     id = [0, 0, 0]}.
asn_choose_tid() -> 
    #'TerminationID'{wildcard = [[(2#01000000 + first_bit())]],
		     id = [0, 0, 0]}.


%%----------------------------------------------------------------------
%% Encode without wildcards
%%----------------------------------------------------------------------
encode1(IDs,LevelConfig) when is_list(LevelConfig) ->
    megaco_binary_term_id_gen:encode_without_wildcards(IDs, LevelConfig);


%% This is only temporary. Eventually a proper encoder for this case
%% should be implemented
encode1(IDs,LevelConfig) when is_integer(LevelConfig) ->
    %% megaco_binary_term_id_8lev:encode_without_wildcards(IDs, LevelConfig).
    encode1(IDs,lists:duplicate(LevelConfig,8)). 


%%----------------------------------------------------------------------
%% Encode with wildcards
%%----------------------------------------------------------------------
encode2(IDs,LevelConfig) when is_list(LevelConfig) ->
    megaco_binary_term_id_gen:encode_with_wildcards(IDs, LevelConfig);


%% This is only temporary. Eventually a proper encoder for this case
%% should be implemented
encode2(IDs,LevelConfig) when is_integer(LevelConfig) ->
    %% megaco_binary_term_id_8lev:encode_with_wildcards(IDs, LevelConfig).
    encode2(IDs,lists:duplicate(LevelConfig,8)).


%%----------------------------------------------------------------------
%% Convert a ASN.1 termination id into a 'TerminationId' record
%% Return {ok, TerminationId} | {error, Reason}
%%----------------------------------------------------------------------

decode(_Config, TermId) when (TermId =:= ?asn_root_termination_id) ->
    {ok, ?megaco_root_termination_id};
decode(Config, #'TerminationID'{wildcard = [], id = IDs}) ->
    case (catch decode1(IDs,Config)) of
	{'EXIT',Reason} ->
	    {error,Reason};
	MegacoTid ->
	    {ok,MegacoTid}
    end;
decode(Config, #'TerminationID'{wildcard = Wildcards, id = IDs}) ->
    case (catch decode2(Wildcards,IDs,Config)) of
	{'EXIT',Reason} ->
	    {error,Reason};
	MegacoTid ->
	    {ok,MegacoTid}
    end;
decode(_Config, TermId) ->
    {error, {bad_type, TermId}}.


%%----------------------------------------------------------------------
%% Decode without wildcards
%%----------------------------------------------------------------------
decode1(IDs, Lc) when is_list(Lc) ->
    megaco_binary_term_id_gen:decode_without_wildcards(IDs, Lc);

%% This is only temporary. Eventually a proper encoder for this case
%% should be implemented
decode1(IDs, Lc) when is_integer(Lc) ->
    %% megaco_binary_term_id_8lev:decode_without_wildcards(IDs, Lc).
    decode1(IDs,lists:duplicate(Lc,8)). 


%%----------------------------------------------------------------------
%% Decode with wildcards
%%----------------------------------------------------------------------
decode2(Wildcards, IDs, Lc) when is_list(Lc) ->
    megaco_binary_term_id_gen:decode_with_wildcards(Wildcards, IDs, Lc);

%% This is only temporary. Eventually a proper encoder for this case
%% should be implemented
decode2(Wildcards, IDs, Lc) when is_integer(Lc) ->
    %% megaco_binary_term_id_8lev:decode_with_wildcards(Wildcards, IDs, Lc);
    decode2(Wildcards, IDs, lists:duplicate(Lc,8)).



