/***************************************************************************
 *   copyright           : (C) 2004 by Hendrik Sattler                     *
 *   mail                : post@hendrik-sattler.de                         *
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 ***************************************************************************/

#include "helper.h"
#include "config.h"
#include "options.h"

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <strings.h>
#include <ctype.h>
#include <stdlib.h>

#if defined(WINDOWS_API)
#define _WIN32_IE 0x0500 /* IE 5.0 is required, not sure why */
#include <shlobj.h> //link with -lshell32 or -lshfolder
#include <shlwapi.h> //also link with -lshlwapi
#else
#include <pwd.h>
#endif

char* get_homedir () {
#if defined(WINDOWS_API)
  static char* retval = NULL;
  HRESULT rc;
  
  if (retval == NULL) {
    retval = mem_alloc(MAX_PATH,1);
    rc = SHGetFolderPathA(NULL,CSIDL_APPDATA,NULL,
                          SHGFP_TYPE_CURRENT,retval);
    if (rc == S_FALSE || rc == E_INVALIDARG) {
      mem_realloc(retval,0);
      retval = str_dup(".");
    }
  }
  return retval;
#else
  static struct passwd* pwentry = NULL;

  pwentry = getpwuid(getuid());
  if (pwentry != NULL)  return str_dup(pwentry->pw_dir);
  return str_dup(getenv("HOME"));
#endif
}

char* configfile_get_path (char* package, char* filename) {
  char* retval;
  char* homedir;

  if (str_len(package) == 0 ||
      str_len(filename) == 0)
    return NULL;

  homedir = get_homedir();
  if (str_len(homedir) > 0) {
    retval = mem_alloc(strlen(homedir)+2
		       +strlen(package)+1
		       +strlen(filename)+1,1);
#if defined(WINDOWS_API)
    retval = str_dup(homedir);
    retval = mem_realloc(retval,MAX_PATH);
    PathAppendA(retval,package);
    PathAppendA(retval,filename);
#else
    sprintf(retval,"%s%s.%s/%s",
	    homedir,
	    (homedir[strlen(homedir)] == '/') ? "" : "/",
	    package,
	    filename);
#endif
  } else {
    retval = NULL;
  }
  mem_realloc(homedir,0);
  return retval;
}

int configfile_parse (char* filepath,
		      struct args_def* list,
		      void (*arg_fill) (int short_opt,
					const char* long_opt,
					char* argument))
{
  char** retval = NULL;
  int entrycount = 2; //not 0 because last entry must be NULL
  int current = 0;
  int status = -1;
  FILE* fd = NULL;
  struct stat fileinfo;
  char* line = NULL;
  char* left = NULL;
  char* right = NULL;
  char* temp = NULL;

  if (filepath == NULL) return -1;
  status = open(filepath,O_RDONLY);
  if (status == -1) return -1;
  if ((fd = fdopen(status,"r")) == NULL ||
      fstat(status,&fileinfo) == -1) {
    fclose(fd);
    return -1;
  }
  if (fileinfo.st_size == 0) {
    fclose(fd);
    return 0;
  }

  retval = mem_realloc(retval,entrycount*sizeof(*retval));
  retval[current++] = filepath;

  line = mem_alloc(fileinfo.st_size+1,1);
  do {
    //read a line from the configuration file
    if (fgets(line,fileinfo.st_size+1,fd) == NULL) break;
    if (*line != '#') {
      //remove end of line characters
      right = strchr(line,'\r');
      if (right != NULL) *right=0;
      right = strchr(line,'\n');
      if (right != NULL) *right=0;

      //skip possible spaces at beginning of line
      left = line;
      while (isspace((int)*left) != 0) ++left;
      if (str_len(left)) {
	++entrycount;
	//find seperator
	right = strchr(left,'=');
	if (right != NULL) {
	  temp = right;
	  //find right part
	  do { ++right; } while (isspace((int)*right) != 0);
	} else {
	  temp = left+strlen(left);
	}
	//find right end of left part
	do { --temp; } while (isspace((int)*temp) != 0);
	*(++temp) = 0;

	retval = mem_realloc(retval,entrycount*sizeof(*retval));
	retval[current] = mem_alloc((2+(temp-left)+1+str_len(right)+1)*sizeof(**retval),1);
	snprintf(retval[current],2+(temp-left)+1+str_len(right)+1,"--%s%s%s",
		 left,(right!=NULL)?"=":"",(right!=NULL)?right:"");
	++current;
      }
    }
  } while (1);
  mem_realloc(line,0);
  retval[current] = NULL;
  fclose(fd);
  
  mem_realloc(args_parse(current,retval,list,arg_fill),0);
  for (--current; current > 0; --current) {
    mem_realloc(retval[current],0);
  }
  mem_realloc(retval,0);
  return entrycount-2;
}
