#include "LibItsDenm_TestSystem.hh"

#include "DENMCodec.hh"
#include "Asn1cEncDec.hh"
#include "DENM.h"

#include "loggers.hh"

int DENMCodec::encode (const DENM__PDU__Descriptions::DENM& p_denm, OCTETSTRING& p_data)
{
  loggers::get_instance().log_msg(">>> DENMCodec::encode: ", p_denm);
  
  BITSTRING b;
  int rc = asnCodec.encode(p_denm, b);
  if(rc){
    p_data = bit2oct(b);
  }
  
  loggers::get_instance().log("<<< DENMCodec::encode: %d", rc);
  return rc;
}

int DENMCodec::decode (const OCTETSTRING& p_data, DENM__PDU__Descriptions::DENM& p_denm, Params* params)
{
  loggers::get_instance().log(">>> DENMCodec::decode");
  
  int rc = asnCodec.decode(oct2bit(p_data), p_denm);
  if(rc) {
    // TODO: fill other Indication fields
  }
  
  loggers::get_instance().log("<<< DENMCodec::decode: %d", rc);
  return rc;
}

int DENMPDUCodec::encode (const DENM__PDU__Descriptions::DENM& p_denm, BITSTRING& p_data)
{
  loggers::get_instance().log_msg(">>> DENMPDUCodec::encode: ", p_denm);
  
  int rc = -1;
  // Encode as BER
  // Encode message in BER (CER variant, but can be any)
  TTCN_EncDec::set_error_behavior(TTCN_EncDec::ET_ALL, TTCN_EncDec::EB_WARNING);
  TTCN_Buffer ber_buf;
  ber_buf.clear();
  p_denm.encode(DENM__PDU__Descriptions::DENM_descr_, ber_buf, TTCN_EncDec::CT_BER, BER_ENCODE_CER);
  ber_buf.rewind();
  loggers::get_instance().log_to_hexa("DENMPDUCodec::encode: BER encoding=", ber_buf);

  // Recode p_data as PER
  TTCN_Buffer per_buf;
  if (asn1c_ber2per(asn_DEF_DENM, ber_buf, per_buf)) {
    per_buf.clear();
    rc = per_buf.get_len() * 8;
    p_data = BITSTRING(rc, per_buf.get_data());
  }
  
  loggers::get_instance().log("<<< DENMPDUCodec::encode: %d", rc);
  return rc;
}

int DENMPDUCodec::decode (const BITSTRING& p_data, DENM__PDU__Descriptions::DENM& p_denm)
{
  loggers::get_instance().log(">>> DENMPDUCodec::decode");

  int rc = -1;
  // Recode p_data to ber
  TTCN_Buffer per_buf, ber_buf;
  per_buf = TTCN_Buffer(bit2oct(p_data));
  loggers::get_instance().log_to_hexa("DENMPDUCodec::decode: PER=", per_buf);
  ber_buf.clear();
  if (asn1c_per2ber(asn_DEF_DENM, per_buf, ber_buf)) {
    loggers::get_instance().log_to_hexa("DENMPDUCodec::decode: BER=", ber_buf);
    TTCN_EncDec::set_error_behavior(TTCN_EncDec::ET_ALL, TTCN_EncDec::EB_WARNING);
    ber_buf.rewind();
    p_denm.decode(DENM__PDU__Descriptions::DENM_descr_, ber_buf, TTCN_EncDec::CT_BER, BER_ACCEPT_ALL);
    rc = ber_buf.get_len() * 8;
  }
  
  loggers::get_instance().log("<<< DENMPDUCodec::decode: %d", rc);
  return rc;
}
