/*!
 * \file      ng_nas_ul_codec.cc
 * \brief     CC file for NG_NAS protocol codec.
 * \author    ETSI TTF041
 * \copyright ETSI Copyright Notification
 *            No part may be reproduced except as authorized by written permission.
 *            The copyright and the foregoing restriction extend to reproduction in all media.
 *            All rights reserved.
 * \version   0.1
 */

#include <stdexcept>
#include <regex>
#include <string>

//#include "ng_nas_ul_codec_factory.hh"

#include "loggers.hh"

#include "NG_NAS_TypeDefs.hh"
#include "NG_NAS_MsgContainers.hh"
#include "ng_nas_ul_codec.hh"


int ng_nas_ul_codec::encode (const NG__NAS__MsgContainers::NG__NAS__UL__Message__Type& body, OCTETSTRING& data)
{
  loggers::get_instance().log_msg(">>> ng_nas_ul_codec::encode: ", (const Base_Type&)body);

  /*if (body.raw().is_present() && body.raw().is_bound()) {
    const CHARSTRING& v = static_cast<const CHARSTRING&>(*body.raw().get_opt_value());
    data = char2oct(v);
  } else {*/
  TTCN_EncDec::clear_error();
  TTCN_EncDec::set_error_behavior(TTCN_EncDec::ET_ALL, TTCN_EncDec::EB_DEFAULT);
  TTCN_Buffer encoding_buffer;
    
        if (body.ischosen(NG__NAS__MsgContainers::NG__NAS__UL__Message__Type::ALT_authentication__Failure)) {  
  }else if (body.ischosen(NG__NAS__MsgContainers::NG__NAS__UL__Message__Type::ALT_authentication__Response)) {     
  }else if (body.ischosen(NG__NAS__MsgContainers::NG__NAS__UL__Message__Type::ALT_configuration__Update__Complete)){
  }else if (body.ischosen(NG__NAS__MsgContainers::NG__NAS__UL__Message__Type::ALT_cp__Service__Request)) {                
  }else if (body.ischosen(NG__NAS__MsgContainers::NG__NAS__UL__Message__Type::ALT_deregistration__Accept)) { 
  }else if (body.ischosen(NG__NAS__MsgContainers::NG__NAS__UL__Message__Type::ALT_deregistration__RequestMO)) {     
  }else if (body.ischosen(NG__NAS__MsgContainers::NG__NAS__UL__Message__Type::ALT_gmm__Status)) {      
  }else if (body.ischosen(NG__NAS__MsgContainers::NG__NAS__UL__Message__Type::ALT_gsm__Status)) {     		
  }else if (body.ischosen(NG__NAS__MsgContainers::NG__NAS__UL__Message__Type::ALT_network__Slice__Specific__Authentication__Complete)) {
  }else if (body.ischosen(NG__NAS__MsgContainers::NG__NAS__UL__Message__Type::ALT_identity__Response)) {     
  }else if (body.ischosen(NG__NAS__MsgContainers::NG__NAS__UL__Message__Type::ALT_notification__Response)) {     	 
  }else if (body.ischosen(NG__NAS__MsgContainers::NG__NAS__UL__Message__Type::ALT_pdu__Session__Authentication__Complete)) {
  }else if (body.ischosen(NG__NAS__MsgContainers::NG__NAS__UL__Message__Type::ALT_pdu__Session__Establishment__Request)) {
  }else if (body.ischosen(NG__NAS__MsgContainers::NG__NAS__UL__Message__Type::ALT_pdu__Session__Modification__Command__Reject)) {     
  }else if (body.ischosen(NG__NAS__MsgContainers::NG__NAS__UL__Message__Type::ALT_pdu__Session__Modification__Complete)) {
  }else if (body.ischosen(NG__NAS__MsgContainers::NG__NAS__UL__Message__Type::ALT_pdu__Session__Modification__Request)) {     
  }else if (body.ischosen(NG__NAS__MsgContainers::NG__NAS__UL__Message__Type::ALT_pdu__Session__Release__Complete)) {     
  }else if (body.ischosen(NG__NAS__MsgContainers::NG__NAS__UL__Message__Type::ALT_pdu__Session__Release__Request)) {  
  }else if (body.ischosen(NG__NAS__MsgContainers::NG__NAS__UL__Message__Type::ALT_registration__Complete)) {     
  }else if (body.ischosen(NG__NAS__MsgContainers::NG__NAS__UL__Message__Type::ALT_registration__Request)) {     
  }else if (body.ischosen(NG__NAS__MsgContainers::NG__NAS__UL__Message__Type::ALT_security__Mode__Complete)) {     
  }else if (body.ischosen(NG__NAS__MsgContainers::NG__NAS__UL__Message__Type::ALT_security__Mode__Reject)) {     
  }else if (body.ischosen(NG__NAS__MsgContainers::NG__NAS__UL__Message__Type::ALT_security__Protected__Nas__Message)) { 
  }else if (body.ischosen(NG__NAS__MsgContainers::NG__NAS__UL__Message__Type::ALT_service__Request)) {     
  }else if (body.ischosen(NG__NAS__MsgContainers::NG__NAS__UL__Message__Type::ALT_ul__Nas__Transport)) {   
  }else if (body.ischosen(NG__NAS__MsgContainers::NG__NAS__UL__Message__Type::ALT_nssai__Delete__Response)) {  
  }else{}

    /*const NG__NAS__MsgContainers::NG__NAS__UL__Message__Type& msg = body.msg();
    CHARSTRING h("<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\" ?>\n");
    encoding_buffer.put_s(h.lengthof(), (const unsigned char*)static_cast<const char*>(h));
    if (msg.ischosen(NG__NAS__MsgContainers::NG__NAS__UL__Message__Type::ALT_locationRequest)) {
      const urn__ietf__params__xml__ns__geopriv__ng_nas::LocationRequestType& location_request = msg.locationRequest();
      loggers::get_instance().log_msg("ng_nas_ul_codec::encode: Process LocationRequestType", (const Base_Type&)location_request);
      location_request.encode(urn__ietf__params__xml__ns__geopriv__ng_nas::LocationRequest_descr_, encoding_buffer, TTCN_EncDec::CT_XER, XER_EXTENDED);
    } else if  (msg.ischosen(NG__NAS__MsgContainers::NG__NAS__UL__Message__Type::ALT_locationResponse)) {
      const urn__ietf__params__xml__ns__geopriv__ng_nas::LocationResponseType& location_response = msg.locationResponse();
      loggers::get_instance().log_msg("ng_nas_ul_codec::encode: Process LocationResponseType", (const Base_Type&)location_response);
      location_response.encode(urn__ietf__params__xml__ns__geopriv__ng_nas::LocationResponse_descr_, encoding_buffer, TTCN_EncDec::CT_XER, XER_EXTENDED);
    } else {
      loggers::get_instance().warning("ng_nas_ul_codec::encode: Unsupported variant");
      return -1;
    }
    data = OCTETSTRING(encoding_buffer.get_len(), encoding_buffer.get_data());
    { // TITAN issue: variant "name as 'device'"; does not work, need to replace "deviceIdenty" by "device"
      std::string s(static_cast<const unsigned char*>(data), data.lengthof() + static_cast<const unsigned char*>(data));
      size_t idx = 0;
      std::string f("deviceIdentity");
      std::string t("device");
      while ((idx = s.find(f)) != std::string::npos) {
        s.replace(idx, f.length(), t);
        idx += t.length();
      } // End of 'while' statement

      // NG112-2021: Apply draft-ietf-geopriv-ng_nas-identity-extensions-06: Use of Device Identity in HTTP-Enabled Location Delivery (HELD) draft-ietf-geopriv-ng_nas-identity-extensions-06
      // FIXME: Add parameter to enable/disable draft-ietf-geopriv-ng_nas-identity-extensions-06 support
      f.assign("xmlns:id");
      t.assign("xmlns");
      while ((idx = s.find(f)) != std::string::npos) {
        s.replace(idx, f.length(), t);
        idx += t.length();
      } // End of 'while' statement
      f.assign("id:device");
      t.assign("device");
      while ((idx = s.find(f)) != std::string::npos) {
        s.replace(idx, f.length(), t);
        idx += t.length();
      } // End of 'while' statement
      f.assign("device:id");
      while ((idx = s.find(f)) != std::string::npos) {
        s.replace(idx, f.length(), t);
        idx += t.length();
      } // End of 'while' statement
      f.assign("xmlns:ng_nas");
      t.assign("xmlns");
      while ((idx = s.find(f)) != std::string::npos) {
        s.replace(idx, f.length(), t);
        idx += t.length();
      } // End of 'while' statement
      f.assign("ng_nas:location");
      t.assign("location");
      while ((idx = s.find(f)) != std::string::npos) {
        s.replace(idx, f.length(), t);
        idx += t.length();
      } // End of 'while' statement
      f.assign("location:ng_nas");
      while ((idx = s.find(f)) != std::string::npos) {
        s.replace(idx, f.length(), t);
        idx += t.length();
      } // End of 'while' statement

      data = OCTETSTRING(s.length(), (const unsigned char*)s.c_str());
    }
  }*/
  data = int2oct(0,1);
  loggers::get_instance().log_msg("ng_nas_ul_codec::encode: After encoding: ", data);
  
  loggers::get_instance().log("<<< ng_nas_ul_codec::encode");
  return -1;
}

int ng_nas_ul_codec::decode (const OCTETSTRING& p_data, NG__NAS__MsgContainers::NG__NAS__UL__Message__Type& body, params* p_params)
{
  loggers::get_instance().log_msg(">>> ng_nas_ul_codec::decode: p_data=", p_data);

  /*// Sanity checks
  params::const_iterator it;
  if (p_params == nullptr) {
    loggers::get_instance().warning("ng_nas_ul_codec::decode: Failed to access p_params (null pointer)");
    return -1;
  } else {
    it = p_params->find("decode_str");
    if (it == p_params->cend()) {
      loggers::get_instance().warning("ng_nas_ul_codec::decode: Failed to access p_params item (decode_str)");
      return -1;
    }
  }
  
  loggers::get_instance().log_msg("body: ", body);
  NG__NAS__MsgContainers::NG__NAS__UL__Message__Type& msg = body.msg();
  body.raw().set_to_omit();
  TTCN_EncDec::set_error_behavior(TTCN_EncDec::ET_ALL, TTCN_EncDec::EB_DEFAULT);
  TTCN_EncDec::clear_error();
  TTCN_Buffer decoding_buffer(OCTETSTRING(it->second.length(), (const unsigned char*)it->second.c_str()));

  if ((it->second.find("<locationRequest") != std::string::npos) || (it->second.find(":locationRequest") != std::string::npos)) {
    urn__ietf__params__xml__ns__geopriv__ng_nas::LocationRequestType location_request;
    location_request.decode(urn__ietf__params__xml__ns__geopriv__ng_nas::LocationRequest_descr_, decoding_buffer, TTCN_EncDec::CT_XER, XER_EXTENDED);
    msg.locationRequest() = location_request;
  } else if ((it->second.find("<locationResponse") != std::string::npos) || (it->second.find(":locationResponse") != std::string::npos)) {
    urn__ietf__params__xml__ns__geopriv__ng_nas::LocationResponseType location_response;
    location_response.decode(urn__ietf__params__xml__ns__geopriv__ng_nas::LocationResponse_descr_, decoding_buffer, TTCN_EncDec::CT_XER, XER_EXTENDED);
    msg.locationResponse() = location_response;
  } else if ((it->second.find("<presence") != std::string::npos) || (it->second.find(":presence") != std::string::npos)) {
    urn__ietf__params__xml__ns__pidf::Presence presence;
    presence.decode(urn__ietf__params__xml__ns__pidf::Presence_descr_, decoding_buffer, TTCN_EncDec::CT_XER, XER_EXTENDED);
    msg.presence() = presence;
  } else if ((it->second.find("<error") != std::string::npos) || (it->second.find(":error") != std::string::npos)) {
    urn__ietf__params__xml__ns__geopriv__ng_nas::Error error;
    error.decode(urn__ietf__params__xml__ns__geopriv__ng_nas::Error_descr_, decoding_buffer, TTCN_EncDec::CT_XER, XER_EXTENDED);
    msg.errorType() = error;
  } else {
    loggers::get_instance().warning("ng_nas_ul_codec::decode: Unsupported variant");
    return -1;
  }
  
  loggers::get_instance().log_msg("<<< ng_nas_ul_codec::decode: ", (const Base_Type&)msg);*/
  return -1;
}

//ng_nas_ul_codec_factory ng_nas_ul_codec_factory::_f;
