#define _XOPEN_SOURCE

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <memory.h>
#include <time.h>
#include <stdint.h>
#include "message_file.h"

namespace
{
char decode[256];
char encode[256][3];
bool code_init_flag=false;

void init_code()
{
	memset(decode,0,sizeof(decode));
	memset(encode,0,sizeof(encode));
	for(int c='A';c<='F';c++)
		decode[c]=c-'A'+10;

	for(int c='0';c<='9';c++)
		decode[c]=c-'0';
	
	for(int i=0;i<256;i++)
	{
		sprintf(encode[i],"%02X",i);
	}
	
	decode['\r']=-1;
	decode['\n']=-1;
	decode[' ']=-1;
}

inline int ch2int(const char c)
{
	return (int) (uint8_t) c;
}

inline int convert(const char*p,char*o)
{
	char c;
	char*r=o;
	for(;*p;p++)
	{
		if(decode[ch2int(*p)]<0)
			continue;

		 c=decode[ch2int(*p++)]<<4;
		*o++=c+decode[ch2int(*p)];
	}
	return o-r;
}
}

message_file::message_file(FILE*fp)
{
	m_last_line[0]=0;
	m_file=fp;
	m_owner=false;
	
	if(!code_init_flag)
	{
		init_code();
		code_init_flag=true;
	}
}

message_file::message_file(const char*fname)
{
	m_last_line[0]=0;
	m_file=fopen(fname,"r");
	m_owner=true;
	
	if(!code_init_flag)
	{
		init_code();
		code_init_flag=true;
	}
}

message_file::~message_file()
{
	if(m_owner)
		fclose(m_file);
}

inline const char* now(char*date_str,uint64_t time)
{
	time_t ntime=time/1000;
	struct tm buff;
	const struct tm*t=localtime_r(&ntime, &buff);

	sprintf(date_str,"%d-%02d-%02d %02d:%02d:%02d.%03d" ,
			t->tm_year+1900,t->tm_mon+1,t->tm_mday,
			t->tm_hour,t->tm_min,t->tm_sec,(int)(time%1000));

	return date_str;
}

int message_file::put_line(uint64_t time,char*buf,int buflen)
{
	char b[8192];

	printf("[%s]\n",now(b,time));
	int n=0,t;
	for(int i=0;i<buflen;i++)
	{
		t=(int)(unsigned char)buf[i];
		n+=sprintf(&b[n],"%s ",encode[t]);
	}

	printf("%s\n",b);

	return 0;
}

int message_file::get_line(uint64_t*time,char*buf,int buflen)
{
	const char*p;
	while(m_last_line[0]!='[')
	{ 
		if(fgets(m_last_line,sizeof(m_last_line),m_file)==nullptr)
			return 0;
	}

	{
		struct tm tm;
		memset(&tm, 0, sizeof(struct tm));
		const char*ms=strptime(&m_last_line[1], "%Y-%m-%d %H:%M:%S", &tm);

		*time=1000*mktime(&tm)+atoi(ms+1);
	}

	char*o=buf;
	for(;;)
	{
		if(nullptr==(p=fgets(m_last_line,sizeof(m_last_line),m_file)))
			return 0;

		if(*p=='[')
			break;

		o+=convert(p,o);
	}

	return o-buf;
}

