#include "http_codec_emtel.hh"

#include "loggers.hh"

bool http_codec_emtel::encode_body_xml(const LibHttp__XmlMessageBodyTypes::XmlBody &p_xml_body, OCTETSTRING &p_encoding_buffer, const std::string &p_content_type) {
  loggers::get_instance().log(">>> http_codec_emtel::encode_body_xml");

  std::map<std::string, std::unique_ptr<codec_gen<Record_Type, Record_Type> > >::const_iterator it;
  bool processed = false;
  loggers::get_instance().log("http_codec_emtel::encode_body_xml: Content-Type:'%s'", p_content_type.c_str());
  if (p_content_type.find("held") != std::string::npos) {
    it = _codecs.find("held"); // TODO Use params
    if (it != _codecs.cend()) {
      loggers::get_instance().log("http_codec_emtel::encode_body_xml: Call 'held_codec'");
      _codecs["held"]->encode((Record_Type&)p_xml_body, p_encoding_buffer); // TODO Use params
      processed = true;
    }
  } else if (p_content_type.find("lost") != std::string::npos) {
    it = _codecs.find("lost"); // TODO Use params
    if (it != _codecs.cend()) {
      loggers::get_instance().log("http_codec_emtel::encode_body_xml: Call 'lost_codec'");
      _codecs["lost"]->encode((Record_Type&)p_xml_body, p_encoding_buffer); // TODO Use params
      processed = true;
    }
  } // TODO Add new HTTP message codec_gen here
  if (!processed) {
    loggers::get_instance().warning("http_codec_emtel::encode_body_xml: Unsupported HTTP codec_gen, use raw field as default");
    p_encoding_buffer = OCTETSTRING(0, nullptr);
  }

  return true;
}

bool http_codec_emtel::decode_body_xml(const OCTETSTRING &p_data, LibHttp__XmlMessageBodyTypes::XmlBody &p_xml_body, const std::string &p_content_type, params* p_params) {
  loggers::get_instance().log(">>> http_codec_emtel::decode_body_xml");

  if (
      ((*p_params)["decode_str"].find("=\"urn:ietf:params:xml:ns:geopriv:held\"") != std::string::npos) ||
      ((*p_params)["decode_str"].find("=\"urn:ietf:params:xml:ns:pidf\"") != std::string::npos)
      ) {
    loggers::get_instance().log("http_codec_emtel::decode_body_xml: Find 'urn:ietf:params:xml:ns:geopriv:held'");
    if (_codecs["held"].get() != nullptr) {
      loggers::get_instance().log("http_codec_emtel::decode_body_xml: Call 'held_codec'");
      if (_codecs["held"]->decode(p_data, (Record_Type&)p_xml_body, p_params) == -1) {
        loggers::get_instance().warning("http_codec_emtel::decode_body_xml: Failed to decode HELD message");
        p_xml_body.raw() = CHARSTRING(p_data.lengthof(), (char*)static_cast<const unsigned char*>(p_data));
      } else {
        loggers::get_instance().log_msg("http_codec_emtel::decode_body_xml: Decoded message:", p_xml_body);
      }
    } else {
      loggers::get_instance().warning("http_codec_emtel::decode_body_xml: No codec_gen for HELD");
      p_xml_body.raw() = CHARSTRING(p_data.lengthof(), (char*)static_cast<const unsigned char*>(p_data));
    }
  } else if ((*p_params)["decode_str"].find("=\"urn:ietf:params:xml:ns:lost1\"") != std::string::npos) {
    loggers::get_instance().log("http_codec_emtel::decode_body_xml: Find 'urn:ietf:params:xml:ns:lost1'");
    if (_codecs["lost"].get() != nullptr) {
      loggers::get_instance().log("http_codec_emtel::decode_body_xml: Call 'lost_codec'");
      if (_codecs["lost"]->decode(p_data, (Record_Type&)p_xml_body, p_params) == -1) {
        loggers::get_instance().warning("http_codec_emtel::decode_body_xml: Failed to decode LOST message");
        p_xml_body.raw() = CHARSTRING(p_data.lengthof(), (char*)static_cast<const unsigned char*>(p_data));
      } else {
        loggers::get_instance().log_msg("http_codec_emtel::decode_body_xml: Decoded message:", p_xml_body);
      }
    } else {
      loggers::get_instance().warning("http_codec_emtel::decode_body_xml: No codec_gen for LOST");
      p_xml_body.raw() = CHARSTRING(p_data.lengthof(), (char*)static_cast<const unsigned char*>(p_data));
    }
  } else {
    loggers::get_instance().warning("http_codec_emtel::decode_body_xml: No XML codec_gen found");
    p_xml_body.raw() = CHARSTRING(p_data.lengthof(), (char*)static_cast<const unsigned char*>(p_data));
  }
  
  return true;
}

bool http_codec_emtel::encode_body_json(const LibHttp__JsonMessageBodyTypes::JsonBody &p_json_body, OCTETSTRING &p_encoding_buffer, const std::string &p_content_type) {
  loggers::get_instance().log(">>> http_codec_emtel::encode_body_json");

  std::map<std::string, std::unique_ptr<codec_gen<Record_Type, Record_Type> > >::const_iterator it;
  bool processed = false;
  loggers::get_instance().log("http_codec_emtel::encode_body_json: Content-Type:'%s'", p_content_type.c_str());
  if (p_content_type.find("json") != std::string::npos) {
    it = _codecs.find("json"); // TODO Use params
    if (it != _codecs.cend()) {
      loggers::get_instance().log("http_codec_emtel::encode_body_json: Call 'json_codec'");
      _codecs["json"]->encode((Record_Type&)p_json_body, p_encoding_buffer); // TODO Use params
      processed = true;
    }
  } // TODO Add new HTTP message codec_gen here
  if (!processed) {
    loggers::get_instance().warning("http_codec_emtel::encode_body_json: Unsupported HTTP codec_gen, use raw field as default");
    p_encoding_buffer = OCTETSTRING(0, nullptr);
  }

  return true;  
}
bool http_codec_emtel::decode_body_json(const OCTETSTRING &p_data, LibHttp__JsonMessageBodyTypes::JsonBody &p_json_body, const std::string &p_content_type, params* p_params) {
  loggers::get_instance().log(">>> http_codec_emtel::decode_body_json");

  if (_codecs["json"].get() != nullptr) {
    loggers::get_instance().log("http_codec_emtel::decode_body_json: Call 'json_codec'");
    if (_codecs["json"]->decode(p_data, (Record_Type&)p_json_body, p_params) == -1) {
      loggers::get_instance().warning("http_codec_emtel::decode_body_json: Failed to decode JSON message");
      p_json_body.raw() = CHARSTRING(p_data.lengthof(), (char*)static_cast<const unsigned char*>(p_data));
    } else {
      loggers::get_instance().log_msg("http_codec_emtel::decode_body_json: Decoded message:", p_json_body);
    }
  }

  return true;
}