#pragma once

#include "codec_gen.hh"
#include "params.hh"

#include "osipparser2/osip_parser.h"
#include "osipparser2/sdp_message.h"

namespace LibSip__SIPTypesAndValues {
  class Authorization;
  class CallId;
  class CallInfo;
  class ContentLength;
  class ContentType;
  class CSeq;
  class Event;
  class Expires;
  class From;
  class Geolocation;
  class GeolocationRouting;
  class HostPort;
  class MessageHeader;
  class PreGenRecordOf;
  class PAccessNetworkInfo;
  class PAssociatedURI;
  class Privacy;
  class Route;
  class RecordRoute;
  class RSeq;
  class UserAgent;
  class To;
  class Via;
}

namespace LibSip__Common {
  class SemicolonParam__List;
  class AmpersandParam__List;
}

class sip_codec_headers
{
public:
  explicit sip_codec_headers() { };
  virtual ~sip_codec_headers() { };

public:
  virtual int encode_headers(const LibSip__SIPTypesAndValues::MessageHeader& p_msg_header, osip_message_t* p_sip_message);
  virtual int encode_sip_url(const LibSip__SIPTypesAndValues::SipUrl& p_sip_uri, osip_uri_t** p_uri);
  virtual int encode_accept_header(const LibSip__SIPTypesAndValues::Accept& p_accept, osip_message_t** p_sip_message);
  virtual int encode_accept_contact_header(const LibSip__SIPTypesAndValues::AcceptContact& p_accept_contact, osip_message_t** p_sip_message);
  virtual int encode_allow_header(const OPTIONAL<LibSip__SIPTypesAndValues::Allow>& p_allow, osip_message_t** p_sip_message);
  virtual int encode_authorization_header(const LibSip__SIPTypesAndValues::Authorization& p_authorization, osip_authorization_t** p_authorization_header);
  virtual int encode_call_id_header(const LibSip__SIPTypesAndValues::CallId& p_call_id, osip_call_id_t** p_call_id_header);
  virtual int encode_call_info_header(const OPTIONAL<LibSip__SIPTypesAndValues::CallInfo>& p_call_info, osip_message_t** p_sip_message);
  virtual int encode_contact_header(const LibSip__SIPTypesAndValues::Contact& p_contact, osip_contact_t** p_contact_header); 
  virtual int encode_content_length_header(const LibSip__SIPTypesAndValues::ContentLength& p_contact, osip_content_length_t** p_content_length_header);
  virtual int encode_content_type_header(const LibSip__SIPTypesAndValues::ContentType& p_contact, osip_content_type_t** p_content_type_header);
  virtual int encode_c_seq_header(const LibSip__SIPTypesAndValues::CSeq& p_c_seq, osip_cseq_t** p_c_seq_header);
  virtual int encode_event_header(const OPTIONAL<LibSip__SIPTypesAndValues::Event>& p_event, osip_message_t** p_sip_message);
  virtual int encode_expires_header(const OPTIONAL<LibSip__SIPTypesAndValues::Expires>& p_expires, osip_message_t** p_sip_message);
  virtual int encode_from_header(const LibSip__SIPTypesAndValues::From& p_from, osip_from_t** p_from_header);
  virtual int encode_geolocation_header(const OPTIONAL<LibSip__SIPTypesAndValues::Geolocation>& p_geolocation, osip_message_t** p_sip_message);
  virtual int encode_geolocation_routing_header(const OPTIONAL<LibSip__SIPTypesAndValues::GeolocationRouting>& p_geolocation, osip_message_t** p_sip_message);
  virtual int encode_max_forwards_header(const OPTIONAL<LibSip__SIPTypesAndValues::MaxForwards>& p_max_forwards, osip_message_t** p_sip_message);
  virtual int encode_min_se_header(const OPTIONAL<LibSip__SIPTypesAndValues::MinSE>& p_min_se, osip_message_t** p_sip_message);
  virtual int encode_p_access_network_info_header(const OPTIONAL<LibSip__SIPTypesAndValues::PAccessNetworkInfo>& p_p_access_network_info_header, osip_message_t** p_sip_message);
  virtual int encode_p_associated_uri_header(const OPTIONAL<LibSip__SIPTypesAndValues::PAssociatedURI>& p_p_associated_uri_header, osip_message_t** p_sip_message);
  virtual int encode_privacy_header(const OPTIONAL<LibSip__SIPTypesAndValues::Privacy>& p_privacy_header, osip_message_t** p_sip_message);
  virtual int encode_route_header(const OPTIONAL<LibSip__SIPTypesAndValues::Route>& p_route_header, osip_message_t** p_sip_message);
  virtual int encode_record_route_header(const OPTIONAL<LibSip__SIPTypesAndValues::RecordRoute>& p_record_route_header, osip_message_t** p_sip_message);
  virtual int encode_r_seq_header(const OPTIONAL<LibSip__SIPTypesAndValues::RSeq>& p_r_seq, osip_message_t** p_sip_message);
  virtual int encode_session_expires_header(const OPTIONAL<LibSip__SIPTypesAndValues::SessionExpires>& p_session_expires, osip_message_t** p_sip_message);
  virtual int encode_supported_header(const OPTIONAL<LibSip__SIPTypesAndValues::Supported>& p_supported, osip_message_t** p_sip_message);
  virtual int encode_to_header(const LibSip__SIPTypesAndValues::To& p_to, osip_to_t** p_to_header);
  virtual int encode_user_agent_header(const OPTIONAL<LibSip__SIPTypesAndValues::UserAgent>& p_user_agent, osip_message_t** p_sip_message);
  virtual int encode_via_header(const LibSip__SIPTypesAndValues::Via& p_via, osip_via_t** p_via_header);
  virtual int encode_www_authenticate_header(const LibSip__SIPTypesAndValues::WwwAuthenticate& p_www_authenticate_header, osip_www_authenticate_t** p_www_authenticate);
  
public:
  // TODO Replace const osip_message_t* p_sip_message by header specific type using osip_parser.h/macros such as osip_message_get_accept/osip_accept_t
  virtual void decode_headers(const osip_message_t* p_sip_message, LibSip__SIPTypesAndValues::MessageHeader& p_headers);
  virtual void decode_uri(LibSip__SIPTypesAndValues::SipUrl& p_sip_url, const osip_uri_t* p_uri);
  virtual void decode_accept_header(const osip_message_t* p_sip_message, LibSip__SIPTypesAndValues::Accept& p_accept_header);
  virtual void decode_accept_contact_header(const osip_message_t* p_sip_message, LibSip__SIPTypesAndValues::AcceptContact& p_accept_contact_header);
  virtual void decode_accept_encoding_header(const osip_message_t* p_sip_message, LibSip__SIPTypesAndValues::AcceptEncoding& p_accept_encoding_header);
  virtual void decode_accept_language_header(const osip_message_t* p_sip_message, LibSip__SIPTypesAndValues::AcceptLanguage& p_accept_language_header);
  virtual void decode_alert_info_header(const osip_message_t* p_sip_message, LibSip__SIPTypesAndValues::AlertInfo& p_alert_info_header);
  virtual void decode_allow_header(const osip_message_t* p_sip_message, LibSip__SIPTypesAndValues::Allow& p_allow_header);
  virtual void decode_allow_events_header(const osip_message_t* p_sip_message, LibSip__SIPTypesAndValues::AllowEvents& p_allow_events_header);
  virtual void decode_authorization_header(const osip_message_t* p_sip_message, LibSip__SIPTypesAndValues::Authorization& p_authorization_header);
  virtual void decode_call_id_header(const osip_message_t* p_sip_message, LibSip__SIPTypesAndValues::CallId& p_call_id_header);
  virtual void decode_call_info_header(const osip_message_t* p_sip_message, LibSip__SIPTypesAndValues::CallInfo& p_call_info_header);
  virtual void decode_content_length_header(const osip_message_t* p_sip_message, LibSip__SIPTypesAndValues::ContentLength& p_content_length_header);
  virtual void decode_content_type_header(const osip_message_t* p_sip_message, LibSip__SIPTypesAndValues::ContentType& p_content_type_header);
  virtual void decode_c_seq_header(const osip_message_t* p_sip_message, LibSip__SIPTypesAndValues::CSeq& p_c_seq_header);
  virtual void decode_contact_header(const osip_message_t* p_sip_message, LibSip__SIPTypesAndValues::Contact& p_contact_header);
  virtual void decode_event_header(const osip_message_t* p_sip_event, LibSip__SIPTypesAndValues::Event& p_event_header);
  virtual void decode_expires_header(const osip_message_t* p_sip_expires, LibSip__SIPTypesAndValues::Expires& p_expires_header);
  virtual void decode_from_header(const osip_from_t* p_sip_from, LibSip__SIPTypesAndValues::From& p_from_header);
  virtual void decode_geolocation_header(const osip_message_t* p_sip_message, LibSip__SIPTypesAndValues::Geolocation& p_geolocation_header);
  virtual void decode_geolocation_routing_header(const osip_message_t* p_sip_message, LibSip__SIPTypesAndValues::GeolocationRouting& p_geolocation_routing_header);
  virtual void decode_max_forwards_header(const osip_message_t* p_sip_message, LibSip__SIPTypesAndValues::MaxForwards& p_max_forwards_header);
  virtual void decode_min_se_header(const osip_message_t* p_sip_message, LibSip__SIPTypesAndValues::MinSE& p_min_se_header);
  virtual void decode_p_access_network_info_header(const osip_message_t* p_sip_message, LibSip__SIPTypesAndValues::PAccessNetworkInfo& p_p_access_network_info_header);
  virtual void decode_p_associated_uri_header(const osip_message_t* p_sip_message, LibSip__SIPTypesAndValues::PAssociatedURI& p_p_associated_uri_header);
  virtual void decode_privacy_header(const osip_message_t* p_sip_message, LibSip__SIPTypesAndValues::Privacy& p_privacy_header);
  virtual void decode_route_header(const osip_message_t* p_sip_message, LibSip__SIPTypesAndValues::Route& p_route_header);
  virtual void decode_record_route_header(const osip_message_t* p_sip_message, LibSip__SIPTypesAndValues::RecordRoute& p_record_route_header);
  virtual void decode_r_seq_header(const osip_message_t* p_sip_message, LibSip__SIPTypesAndValues::RSeq& p_r_seq_header);
  virtual void decode_session_expires_header(const osip_message_t* p_sip_message, LibSip__SIPTypesAndValues::SessionExpires& p_session_expires_header);
  virtual void decode_supported_header(const osip_message_t* p_sip_message, LibSip__SIPTypesAndValues::Supported& p_supported_header);
  virtual void decode_to_header(const osip_to_t* p_sip_to, LibSip__SIPTypesAndValues::To& p_to_header);
  virtual void decode_user_agent_header(const osip_message_t* p_user_agent, LibSip__SIPTypesAndValues::UserAgent& p_user_agent_header);
  virtual void decode_via_header(const osip_message_t* p_sip_via_list, LibSip__SIPTypesAndValues::Via& p_via_header);
  virtual void decode_www_authenticate_header(const osip_www_authenticate_t* p_www_authenticate, LibSip__SIPTypesAndValues::WwwAuthenticate& p_www_authenticate_header);

private:
  void encode_host_port(const LibSip__SIPTypesAndValues::HostPort& p_host_port, std::string& p_host, std::string& p_port);
  int encode_semi_colon_params(const LibSip__Common::SemicolonParam__List& p_list, osip_list_t* p_sip_list);
  int encode_ampersand_params(const LibSip__Common::AmpersandParam__List& p_list, osip_list_t** p_sip_list);
  int encode_option_tag_list(const LibSip__SIPTypesAndValues::OptionTag__List& p_options_tags, const std::string& p_field_name, osip_message_t** p_sip_message);
  int encode_server_val_list(const LibSip__SIPTypesAndValues::ServerVal__List& p_server_vals, const std::string& p_field_name, osip_message_t** p_sip_message);

  void decode_host_port(const char* p_host, const char* p_port, LibSip__SIPTypesAndValues::HostPort& p_host_port);
  void decode_semi_colon_params(const std::string& p_params, LibSip__Common::SemicolonParam__List& p_params_list);
  void decode_semi_colon_params(const std::string& p_params, std::string& p_first_param, LibSip__Common::SemicolonParam__List& p_others_params);
  void decode_semi_colon_params(const osip_list_t& p_sip_list, OPTIONAL<LibSip__Common::SemicolonParam__List>& p_list);
  void decode_ampersand_params(const osip_list_t& p_sip_list, OPTIONAL<LibSip__Common::AmpersandParam__List>& p_list);
  void decode_option_tag_list(const char* p_list, OPTIONAL<LibSip__SIPTypesAndValues::OptionTag__List>& p_options_tags);
  void decode_server_val_list(const char* p_list, LibSip__SIPTypesAndValues::ServerVal__List& p_server_vals);

}; // End of class sip_codec_headers
