#include <string>

#include "avp.hh"

#include "loggers.hh"
#include "converter.hh"

avp::avp(const int p_code, const unsigned char p_vendor_specific, const unsigned char p_mandatory, const unsigned char p_protected_, const int p_length, const int p_vendor_id, const int p_encoded_length, const std::vector<unsigned char> p_payload) : _code(p_code), _vendor_specific(p_vendor_specific), _mandatory(p_mandatory), _protected_(p_protected_), _length(p_length), _vendor_id(p_vendor_id), _encoded_length(p_encoded_length), _payload(p_payload),   _avp_header(LibDiameter__Types__Base__AVPs::AVP__Header(p_code, LibDiameter__Types__Base__AVPs::AVP__Flags( int2bit(p_vendor_specific, 1), int2bit(p_mandatory, 1), int2bit(p_protected_, 1), int2bit(0, 5)), p_length, (p_vendor_specific == 0) ? OPTIONAL<INTEGER>(OPTIONAL_OMIT) : OPTIONAL<INTEGER>(p_vendor_id))), _enc_avp() {
  loggers::get_instance().log_msg("avp::avp (1): _avp_header:", _avp_header);
  loggers::get_instance().log_to_hexa("avp::avp (1): _payload:", _payload.data(), _payload.size());
} // End of ctor

avp::avp(const int p_code, const unsigned char p_vendor_specific, const unsigned char p_mandatory, const unsigned char p_protected_, const int p_length, const int p_vendor_id, const int p_encoded_length, const std::vector<unsigned char> p_payload, const OCTETSTRING& p_enc_avp) : _code(p_code), _vendor_specific(p_vendor_specific), _mandatory(p_mandatory), _protected_(p_protected_), _length(p_length), _vendor_id(p_vendor_id), _encoded_length(p_encoded_length), _payload(p_payload),   _avp_header(LibDiameter__Types__Base__AVPs::AVP__Header(p_code, LibDiameter__Types__Base__AVPs::AVP__Flags( int2bit(p_vendor_specific, 1), int2bit(p_mandatory, 1), int2bit(p_protected_, 1), int2bit(0, 5)), p_length, (p_vendor_specific == 0) ? OPTIONAL<INTEGER>(OPTIONAL_OMIT) : OPTIONAL<INTEGER>(p_vendor_id))), _enc_avp(p_enc_avp) {
  loggers::get_instance().log_msg("avp::avp (2): _avp_header:", _avp_header);
  loggers::get_instance().log_to_hexa("avp::avp (2): _payload:", _payload.data(), _payload.size());
  loggers::get_instance().log_msg("avp::avp (2): _enc_avp:", _enc_avp);
} // End of ctor

int avp::get_code() const {
  return _code;
}

int avp::decode_session_id(LibDiameter__Types__Base__AVPs::Session__Id__AVP& p_avp) const {
  loggers::get_instance().log(">>> avp::decode_session_id: '%d'", _code);
  loggers::get_instance().log_to_hexa("avp::decode_session_id: _payload:", _payload.data(), _payload.size());

  p_avp = LibDiameter__Types__Base__AVPs::Session__Id__AVP(LibDiameter__Types__Base__AVPs::AVP__Header(_avp_header), CHARSTRING(converter::get_instance().bytes_to_string(_payload).c_str()));
  loggers::get_instance().log_msg("avp::decode_session_id: p_avp:", p_avp);

  return 0;
}

int avp::decode_auth_session_state(LibDiameter__Types__Base__AVPs::Auth__Session__State__AVP& p_avp) const {
  loggers::get_instance().log(">>> avp::decode_auth_session_state: '%d'", _code);
  loggers::get_instance().log_to_hexa("avp::decode_auth_session_state: _payload:", _payload.data(), _payload.size());

  // Sanity checks
  if (_payload.size() != 4) {
    loggers::get_instance().warning("avp::decode_auth_session_state: Wrong payload length: '%d'", _payload.size());
    return -1;
  }
  p_avp = LibDiameter__Types__Base__AVPs::Auth__Session__State__AVP(LibDiameter__Types__Base__AVPs::AVP__Header(_avp_header), LibDiameter__Types__Base__AVPs::Auth__Session__State__Type(_payload[0] << 24 || _payload[1] << 16 || _payload[2] << 8 || _payload[3]));
  loggers::get_instance().log_msg("avp::decode_auth_session_state: p_avp:", p_avp);

  return 0;
}

int avp::decode_origin_host(LibDiameter__Types__Base__AVPs::Origin__Host__AVP& p_avp) const {
  loggers::get_instance().log(">>> avp::decode_origin_host: '%d'", _code);
  loggers::get_instance().log_to_hexa("avp::decode_origin_host: _payload:", _payload.data(), _payload.size());

  p_avp = LibDiameter__Types__Base__AVPs::Origin__Host__AVP(LibDiameter__Types__Base__AVPs::AVP__Header(_avp_header), CHARSTRING(converter::get_instance().bytes_to_string(_payload).c_str()));
  loggers::get_instance().log_msg("avp::decode_origin_host: p_avp:", p_avp);

  return 0;
}

int avp::decode_origin_realm(LibDiameter__Types__Base__AVPs::Origin__Realm__AVP& p_avp) const {
  loggers::get_instance().log(">>> avp::decode_origin_realm: '%d'", _code);
  loggers::get_instance().log_to_hexa("avp::decode_origin_realm: _payload:", _payload.data(), _payload.size());

  p_avp = LibDiameter__Types__Base__AVPs::Origin__Realm__AVP(LibDiameter__Types__Base__AVPs::AVP__Header(_avp_header), CHARSTRING(converter::get_instance().bytes_to_string(_payload).c_str()));
  loggers::get_instance().log_msg("avp::decode_origin_realm: p_avp:", p_avp);

  return 0;
}

int avp::decode_destination_host(LibDiameter__Types__Base__AVPs::Destination__Host__AVP& p_avp) const {
  loggers::get_instance().log(">>> avp::decode_destination_host: '%d'", _code);
  loggers::get_instance().log_to_hexa("avp::decode_destination_host: _payload:", _payload.data(), _payload.size());

  p_avp = LibDiameter__Types__Base__AVPs::Destination__Host__AVP(LibDiameter__Types__Base__AVPs::AVP__Header(_avp_header), CHARSTRING(converter::get_instance().bytes_to_string(_payload).c_str()));
  loggers::get_instance().log_msg("avp::decode_destination_host: p_avp:", p_avp);

  return 0;
}

int avp::decode_destination_realm(LibDiameter__Types__Base__AVPs::Destination__Realm__AVP& p_avp) const {
  loggers::get_instance().log(">>> avp::decode_destination_realm: '%d'", _code);
  loggers::get_instance().log_to_hexa("avp::decode_destination_realm: _payload:", _payload.data(), _payload.size());

  p_avp = LibDiameter__Types__Base__AVPs::Destination__Realm__AVP(LibDiameter__Types__Base__AVPs::AVP__Header(_avp_header), CHARSTRING(converter::get_instance().bytes_to_string(_payload).c_str()));
  loggers::get_instance().log_msg("avp::decode_destination_realm: p_avp:", p_avp);

  return 0;
}

