#pragma once

// include titan headers 
#include "TTCN3.hh"

// include ASN1C sceleton
#include "asn1c/INTEGER.h"
#include "asn1c/BOOLEAN.h"
#include "asn1c/OCTET_STRING.h"
#include "asn1c/BIT_STRING.h"

extern "C" {
	int asn1c_collect_encoded_data(const void *buffer, size_t size, void *application_specific_key);
}

// OPTIONAL is defined somewhere in WIN32
#ifdef OPTIONAL
#undef OPTIONAL
#endif

//template<typename TT, typename TA>
//TT asn1c2titan(const TA& a) {
//	// default implementation:
//	return TT(a);
//}
//
//// basic types
//void        titan2asn1c(const INTEGER& t, long& a);
//void        titan2asn1c(const INTEGER& t, unsigned long& a);
//void        titan2asn1c(const INTEGER& t, INTEGER_t& a);
//void        titan2asn1c(const BOOLEAN& t, BOOLEAN_t& a);
//void        titan2asn1c(const OCTETSTRING& t, OCTET_STRING_t& a);
//void        titan2asn1c(const BITSTRING& t, BIT_STRING_t& a);
//
//INTEGER     asn1c2titan(const INTEGER_t&);
//INTEGER     asn1c2titan(long);
//OCTETSTRING asn1c2titan(const OCTET_STRING_t&);
//BITSTRING   asn1c2titan(const BIT_STRING_t&);
//
//// template for optional value
//template <typename TT, typename TA>
//OPTIONAL<TT> asn1c2titan_opt(const TA * pa) {
//  if(pa) {
//    return OPTIONAL<TT>(asn1c2titan(*pa));
//  }
//  return OPTIONAL<TT>(OMIT_VALUE);
//}
//
//template <typename TT, typename TA>
//void titan2asn1c_opt(const OPTIONAL<TT> & ot, TA *& a){
//  if(ot.is_present()){
//    a = new TA;
//    titan2asn1c((const TT&)ot, *a);
//  }else{
//    a = NULL;
//  }
//}
//
//template<typename T, typename TS, typename TA>
//void titan2asn1c_seq(const TS& t, TA& a){
//	a.list.array = (T**)calloc(t.n_elem(), sizeof(void*));
//	a.list.count = t.n_elem();
//	a.list.size = sizeof(void*)*a.list.count;
//	for (int i = 0; i < t.n_elem(); i++){
//		a.list.array[i] = (T*)malloc(sizeof(T));
//		titan2asn1c(t[i], *a.list.array[i]);
//	}
//}
//
//template<typename TS, typename TA>
//TS asn1c2titan_seq(const TA& a)
//{
//	TS t;
//	t.set_size(a.list.count);
//	for (int i = 0; i < a.list.count; i++){
//		t[i] = asn1c2titan(*a.list.array[i]);
//	}
//	return t;
//}

int asn1c_per2ber(asn_TYPE_descriptor_t &td, const TTCN_Buffer & per, TTCN_Buffer & ber, void** ctx );
int asn1c_ber2per(asn_TYPE_descriptor_t &td, const TTCN_Buffer & ber, TTCN_Buffer & per, void** ctx );
// int asn1c_oer2xer(asn_TYPE_descriptor_t &td, const TTCN_Buffer & oer, TTCN_Buffer & xer, void** ctx );
// int asn1c_xer2oer(asn_TYPE_descriptor_t &td, const TTCN_Buffer & xer, TTCN_Buffer & oer, void** ctx );
