#include <math.h>

#include <time.h>
#include <string.h>
#include <stdint.h>
#include <gnutls/crypto.h>

#include "CommonDefs.hh"

#ifndef M_PI
#define M_PI 3.14159265358979323846
#endif
#define earthRadius 6378137.0L
#define rbis = ((double)(earthRadius * M_PI / 180))

namespace CommonDefs {

	/**
   * @desc    This external function gets KEY
   * @return  The KEY
   * @see     fx_get...() return bitstring length(256)
   */
   BITSTRING fx__KeyDerivationFunction(const INTEGER& p__KDF, const BITSTRING& p__Key, const OCTETSTRING& p__String){
      if (p__KDF != 1) {
         TTCN_error("fx__KeyDerivationFunction(p__KDF!=1) NOT IMPLEMENTED!");
         return int2bit(0, 0);
      }

      uint8_t out[32];
      TTCN_Buffer ttcn_buf_key(bit2oct(p__Key));
      TTCN_Buffer ttcn_buf_str(p__String);

      gnutls_hmac_fast(GNUTLS_MAC_SHA256, ttcn_buf_key.get_data(), ttcn_buf_key.get_len(),
            ttcn_buf_str.get_data(), ttcn_buf_str.get_len(), out);

      OCTETSTRING res(sizeof(out), out);
      return oct2bit(res);
   }
	/**
   * @desc    This external function gets the current time since 01/01/1970 in UTC format
   * @return  The current time since 01/01/1970 in UTC format in milliseconds
   * @see     fx_getSystemTime() return UInt64
   */
void  fx__GetSystemTime(CommonDefs::Struct__tm__Type& p__Struct__tm, INTEGER& p__TimezoneInfo){
   /* See fx_GetSystemTime() comments in nas.git/ttcn/Lib3GPP/Common/CommonDefs.ttcn: */
   time_t v_Now = time(NULL);
   struct tm v_Tm;
    int timezone;

   if (!localtime_r(&v_Now, &v_Tm)) {
      TTCN_warning("fx__GetSystemTime(): localtime_r() failed!");
      memset(&v_Tm, 0, sizeof(v_Tm));
   }
   timezone = (int)difftime(mktime(gmtime(&v_Now)), v_Now);

   p__Struct__tm.tm__sec() = v_Tm.tm_sec;             /* seconds after the minute    0..61 (tm_sec is generally 0-59. Extra range to accommodate for leap seconds in certain systems) */
   p__Struct__tm.tm__min() = v_Tm.tm_min;             /* minutes after the hour      0..59   */
   p__Struct__tm.tm__hour() = v_Tm.tm_hour;            /* hours since midnight        0..23   */
   p__Struct__tm.tm__mday() = v_Tm.tm_mday;            /* day of the month            1..31   */
   p__Struct__tm.tm__mon() = v_Tm.tm_mon;             /* months since January        0..11   */
   p__Struct__tm.tm__year() = v_Tm.tm_year;            /* years since 1900                    */
   p__Struct__tm.tm__wday() = v_Tm.tm_wday;            /* days since Sunday           0..6    */
   p__Struct__tm.tm__yday() = v_Tm.tm_yday;            /* days since January 1        0..365  */
   p__Struct__tm.tm__isdst() = v_Tm.tm_isdst;            /* Daylight Saving Time flag           */
   p__TimezoneInfo = timezone;
   return;
}
//void fx__CalculateFCS32(BITSTRING const&)   {
 BITSTRING fx__CalculateFCS32(const BITSTRING& p__TMSI){
return int2bit(0, 0);
}

} // namespace CommonDefs
