
#include "stdio.h"
#include "stdlib.h"
#include "string.h"
#include "errno.h"

#include "errormsg.h"
#include "config.h"
#include "img_format.h"

config_t config[17];
int confignum = 0;

static char* trim(char *txt, int tab);
static void storeconfig(char* name, config_t *temp);

static struct {
  char* name;
  unsigned int fmt;
} mp_imgfmt_list[] = {
  {"444p", IMGFMT_444P},
  {"422p", IMGFMT_422P},
  {"411p", IMGFMT_411P},
  {"yuy2", IMGFMT_YUY2},
  {"uyvy", IMGFMT_UYVY},
  {"yvu9", IMGFMT_YVU9},
  {"if09", IMGFMT_IF09},
  {"yv12", IMGFMT_YV12},
  {"i420", IMGFMT_I420},
  {"iyuv", IMGFMT_IYUV},
  {"clpl", IMGFMT_CLPL},
  {"hm12", IMGFMT_HM12},
  {"y800", IMGFMT_Y800},
  {"y8", IMGFMT_Y8},
  {"nv12", IMGFMT_NV12},
  {"nv21", IMGFMT_NV21},
  {"bgr24", IMGFMT_BGR24},
  {"bgr32", IMGFMT_BGR32},
  {"bgr16", IMGFMT_BGR16},
  {"bgr15", IMGFMT_BGR15},
  {"bgr8", IMGFMT_BGR8},
  {"bgr4", IMGFMT_BGR4},
  {"bg4b", IMGFMT_BG4B},
  {"bgr1", IMGFMT_BGR1},
  {"rgb24", IMGFMT_RGB24},
  {"rgb32", IMGFMT_RGB32},
  {"rgb16", IMGFMT_RGB16},
  {"rgb15", IMGFMT_RGB15},
  {"rgb8", IMGFMT_RGB8},
  {"rgb4", IMGFMT_RGB4},
  {"rg4b", IMGFMT_RG4B},
  {"rgb1", IMGFMT_RGB1},
  {"rgba", IMGFMT_RGBA},
  {"argb", IMGFMT_ARGB},
  {"bgra", IMGFMT_BGRA},
  {"abgr", IMGFMT_ABGR},
  { NULL, 0 }
};


static char* trim(char *txt, int tab)
  {
  int i,l;
  char *ret;
  if (strlen(txt)==0) return txt;
  ret=txt;
  l=strlen(ret);
  for(i=0;i<l;i++)
    {
    if ((txt[i]==32) || (tab && txt[i]==9))
      {
      ret++;
      }
      else i=l;
    }
  l=strlen(ret);
  for(i=1;i<l;i++)
    {
    if ((ret[strlen(ret)-1]==32) || (tab && ret[strlen(ret)-1]==9))
      {
      ret[strlen(ret)-1]=0;
      }
    }
  if (txt!=ret) strcpy(txt,ret);
  return txt;  
  }

int strlcmp(char* txt1,char* txt2)
  {
  if (strlen(txt1) != strlen(txt2)) return 0;
  if (strcmp(txt1,txt2) == 0) return 1;
  return 0;
  }

int strcaselcmp(char* txt1,char* txt2)
  {
  if (strlen(txt1) != strlen(txt2)) return 0;
  if (strcasecmp(txt1,txt2) == 0) return 1;
  return 0;
  }

static void storeconfig(char* name, config_t *temp)
{
config_t *to;
to=seekconfigname(name);
if(!to) 
  {
  if(confignum==17) return;
  to=&config[confignum];
  confignum++;
  configclear(to);
  to->logmode=-1;
  to->loglevel=-1;
  to->input=-1;
  to->width=-1;
  to->height=-1;
  to->fps=-1;
  to->freq=-1.0;
  to->format=-1;
  to->smemid=-1;
  to->name=strdup(name);
  }
configmix(to,temp);
}

int get_format(char *data)
{
int i,fmt;
fmt=-1;
if (sscanf(data, "0x%x", &fmt) != 1)
  for(i = 0 ; mp_imgfmt_list[i].name ; i++) {
    if(strcaselcmp(data,mp_imgfmt_list[i].name)) {
      fmt=mp_imgfmt_list[i].fmt;
      break;
    }
  }
return fmt;
}

void listformat(void)
{
int i;
printf("Available formats:");
for(i = 0 ; mp_imgfmt_list[i].name ; i++) printf(" %s",mp_imgfmt_list[i].name);
printf("\n");
return;
}


config_t* seekconfigid(int id)
{
if (id>=confignum) return NULL;
return &config[id];
}

config_t* seekconfigname(char *name)
{
int i,n=-1;
for(i=0;i<confignum;i++) if(strlcmp(config[i].name,name)) {n=i; break;}
if(n==-1) return NULL;
return &config[n];
}


void configclear(config_t *ptr)
{
if(!ptr) return;
ptr->name=NULL;
ptr->loglevel=-1;
ptr->logmode=-1;
ptr->fps=0;
ptr->width=0;
ptr->height=0;
ptr->input=0;
ptr->freq=0.0;
ptr->format=0;
ptr->device=strdup("/dev/video0");
ptr->smemid=1000;
return;
}

void configmix(config_t *to, config_t *from)
{
if(!to) return;
if(!from) return;
if(from==to) return;
if(from->name && !to->name) to->name=strdup(from->name);
if(from->loglevel!=-1) to->loglevel=from->loglevel;
if(from->logmode!=-1) to->logmode=from->logmode;
if(from->width!=-1) to->width=from->width;
if(from->height!=-1) to->height=from->height;
if(from->fps!=-1) to->fps=from->fps;
if(from->input!=-1) to->input=from->input;
if(from->freq!=-1.0) to->freq=from->freq;
if(from->format!=-1) to->format=from->format;
if(from->device) {if(to->device) free(to->device); to->device=strdup(from->device);}
if(from->smemid!=-1) to->smemid=from->smemid;
return;
}


int loadconfig(char *fname)
{
FILE *fh;
int  n;
char *buffer;
char *p;
char *line;
char *section = NULL;
char *name = NULL;
char *data = NULL;
config_t *temp;

section = strdup("default");
if (NULL==(buffer=malloc(BUFFER_SIZE))) {logprint(LEVEL_ERR,"malloc read buffers failed %s",
	strerror(errno)); return 0;}
if (NULL==(temp=malloc(sizeof(config_t)))) {logprint(LEVEL_ERR,"malloc config buffers failed %s",
	strerror(errno)); free(buffer); return 0;}
memset(buffer,0,BUFFER_SIZE);
if (NULL==(fh=fopen(fname,"r"))) {logprint(LEVEL_ERR,"config file open error (%s) %s",
	fname,strerror(errno)); free(temp); free(buffer); return 0;}
n=0;
temp->logmode=-1;
temp->loglevel=-1;
temp->input=-1;
temp->width=-1;
temp->height=-1;
temp->fps=-1;
temp->freq=-1.0;
temp->format=-1;
temp->smemid=-1;
while (!feof(fh))
  {
  fgets(buffer,BUFFER_SIZE,fh);
  n++;
  if (NULL!=(p=strchr(buffer,'\n'))) *p=0;
  if (NULL!=(p=strstr(buffer,"//"))) *p=0;
  line=trim(buffer,1);
  if (strlen(line)==0) line=NULL;
  if ((line) && (*line=='#')) line=NULL;
  if ((line) && (*line=='[') && (line[strlen(line)-1]==']')) {
    storeconfig(section,temp);
    memset(temp,0,sizeof(config_t));
    temp->logmode=-1;
    temp->loglevel=-1;
    temp->width=-1;
    temp->height=-1;
    temp->input=-1;
    temp->fps=-1;
    temp->freq=-1.0;
    temp->format=-1;
    temp->smemid=-1;
    free(section);
    line++;
    if(NULL!=(p=strchr(line,']'))) *p=0;
    section=strdup(line);
    }
  if ((line) && (NULL==(p=strchr(line,'=')))) line=NULL;
  if (line)
    {
    *p=0;
    p++;
    name=trim(line,1);
    data=trim(p,1);
    if (strlcmp(name,"logmode")) {
	if(strlcmp(section,"default")) temp->logmode = atoi(data); else
	    logprint(LEVEL_INFO,"ignore %i line %s = %s\n",n,name,data); }
    if (strlcmp(name,"loglevel")) {
	if(strlcmp(section,"default")) temp->loglevel = atoi(data); else
	    logprint(LEVEL_INFO,"ignore %i line %s = %s\n",n,name,data); }
    if (strlcmp(name,"tvwidth")) temp->width = atoi(data);
    if (strlcmp(name,"tvheight")) temp->height = atoi(data);
    if (strlcmp(name,"tvfps")) temp->fps = atoi(data);
    if (strlcmp(name,"tvfreq")) temp->freq = atof(data); 
    if (strlcmp(name,"tvformat")) temp->format = get_format(data);
    if (strlcmp(name,"tvdevice")) {if(temp->device) free(temp->device); temp->device = strdup(data);}
    if (strlcmp(name,"tvsmemid")) temp->smemid = atoi(data);
    }
  }
storeconfig(section,temp);
free(section);
fclose(fh);
free(buffer);
return 1;
}
