#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include "common.h"

#include <stdio.h>
#include <locale.h>

FILE* inputf=stdin;
FILE* outputf=stdout;
FILE* failedf=stdout;
bool copy_processed=0;
bool one_field=false;
bool one_line=false;
char output_field_prefix[32];
char input_field_prefix[32];

extern int argc;
extern char **argv;


// tilde (home dir) expansion in path
int expand_path(char* inpath, char* outpath)
{
  if(inpath[0]=='~')
    sprintf(outpath,"%s%s",getenv("HOME"),inpath+1);
  else
    strcpy(outpath,inpath);
  return 0; // no problem
}




/*
parameters:
        -name - field name, long or short
        +prefix - field name with ':' appended if long name
return value:
        1 if correct field name, 0 otherwise
examples:
name    prefix  r.v.
lem     lem:    1
@       @       1
::      'undef' 0
a,b     'undef' 0
*/
int fieldprefix(char *name, char *prefix)
{
  if (ispunct(name[0]) && name[1]=='\0') // correct short name
  {
    strcpy(prefix, name); return 1;
  }

  int i=0;
  while(name[i]!='\0' && isalnum(name[i])) ++i;
  
  if(name[i]=='\0' && i>0) // correct long name
  {
    sprintf(prefix,"%s:",name); return 1;
  }

  // incorrect
  return 0;
}



void set_program_name(char program_name[], char* argv0)
{
  if (char* p_name = strrchr(argv0, '/'))
    strcpy(program_name,p_name+1);
  else
    strcpy(program_name,argv0);
}



extern void process_config_files(gengetopt_args_info* args, char* argv0)
{

  char program_name[256];
  char config_file[256];
  char config_file_tmp[256];

  set_program_name(program_name,argv0);

  // obsługa pliku konfiguracyjnego podanego w linii komend
  if (args->config_given) {
    if (file_accessible(args->config_arg) == 0) {
      if (cmdline_parser_configfile(args->config_arg,
				    args,
				    0, // 0 - nie nadpisuj wartości parametrów
				    0, // 0 - nie inicjuj
				    0) != 0) {
	fprintf(stderr, "Error in config file (%s)\n", args->config_arg);
	exit(1);
      }
    }
  }

  if(args->one_line_given && !one_line) one_line=true, one_field=false;
  if(args->one_field_given && !one_field) one_line=false, one_field=true;

  // obsluga pliku konfiguracyjnego uzytkownika dla programu
  sprintf(config_file_tmp, "%s/%s.conf", USER_CONFIG_DIR, program_name);
  expand_path(config_file_tmp, config_file);
  if (file_accessible(config_file) == 0) {
    if (cmdline_parser_configfile(config_file,
				  args,
				  0, // 0 - nie nadpisuj danych
				  0, // 0 - nie inicjuj struktury
				  0) != 0) {
      fprintf(stderr, "Error in config file (%s)\n", config_file);
      exit(1);
    }
  }

  if(args->one_line_given && !one_line) one_line=true, one_field=false;
  if(args->one_field_given && !one_field) one_line=false, one_field=true;


  // obsluga pliku konfiguracyjnego uzytkownika globalnego
  sprintf(config_file_tmp, "%s/utt.conf", USER_CONFIG_DIR);
  expand_path(config_file_tmp, config_file);
  if (file_accessible(config_file) == 0) {
    if (cmdline_parser_configfile(config_file,
				  args,
				  0, // 0 - nie nadpisuj danych
				  0, // 0 - nie inicjuj struktury
				  0) != 0) {
      fprintf(stderr, "Error in config file (%s)\n", config_file);
      exit(1);
    }
  }

  if(args->one_line_given && !one_line) one_line=true, one_field=false;
  if(args->one_field_given && !one_field) one_line=false, one_field=true;



  // obsluga systemowego pliku konfiguracyjnego dla programu
  sprintf(config_file, "%s/%s.conf", SYSTEM_CONFIG_DIR, program_name);
  if (file_accessible(config_file) == 0) {
    if (cmdline_parser_configfile(config_file,
				  args,
				  0, // 0 - nie zmieniaj danych wczesniejszych
				  0, // 0 - nie inicjuj struktury
				  0  // 0 - nie sprawdzaj wymaganych parametrow
				  ) != 0) {
      fprintf(stderr, "Error in config file (%s)\n", config_file);
      exit(1);
    }
  }

  if(args->one_line_given && !one_line) one_line=true, one_field=false;
  if(args->one_field_given && !one_field) one_line=false, one_field=true;


  // obsluga systemowego pliku konfiguracyjnego globalnego
  sprintf(config_file, "%s/utt.conf", SYSTEM_CONFIG_DIR);
  if (file_accessible(config_file) == 0) {
    if (cmdline_parser_configfile(config_file,
				  args,
				  0, // 0 - nie zmieniaj danych wczesniejszych
				  0, // 0 - nie inicjuj struktury
				  0  // 0 - nie sprawdzaj wymaganych parametrow
				  ) != 0) {
      fprintf(stderr, "Error in config file (%s)\n", config_file);
      exit(1);
    }
  }

  if(args->one_line_given && !one_line) one_line=true, one_field=false;
  if(args->one_field_given && !one_field) one_line=false, one_field=true;

}


void process_common_options(gengetopt_args_info* args, char* argv0)
{
  char program_name[256];

  set_program_name(program_name,argv0);

  setlocale(LC_CTYPE,"");
  setlocale(LC_COLLATE, "");

  if(args->help_given)
      cmdline_parser_print_help ();

  if(args->input_given)
    if(!(inputf=fopen(args->input_arg,"r")))
    {
      fprintf(stderr,"No such file: %s.\n", args->input_arg);
      exit(1);
    }
  
  if(args->output_given)
    if(!(outputf=fopen(args->output_arg,"w")))
    {
      fprintf(stderr,"Cannot open output file: %s.\n", args->output_arg);
      exit(1);
    }
  
  if(args->fail_given)
      if(!(failedf=fopen(args->fail_arg,"w")))
      {
	fprintf(stderr,"Cannot open output file: %s.\n", args->fail_arg);
	exit(1);
      }

  if(args->input_field_given)
    fieldprefix(args->input_field_arg[0],input_field_prefix);
  else
    strcpy(input_field_prefix, "4");

  if(args->output_field_given)
    fieldprefix(args->output_field_arg,output_field_prefix);
  else
    sprintf(output_field_prefix, "%s%c", program_name, INFIELD_SEP);

  if ((args->copy_given))
    copy_processed=true;
}

// sprawdza istnienie pliku
int file_accessible(const char* path) {
    return access(path, R_OK);
}

// sprawdza istnienie pliku konfiguracyjnego
int config_file_exists(const char* dir, const char* filename) {
    struct stat dir_stat;
    struct stat file_stat;

    char* path = (char*)malloc(strlen(dir) + strlen(filename) + 2); // + '\0' + '/'

    sprintf(path, "%s/%s", dir, filename);

    if (stat(dir, &dir_stat) != 0)
	return -1;

    if (stat(path, &file_stat) != 0)
	return -1;

    if (!S_ISDIR(dir_stat.st_mode))
	return -1; // katalog nie jest katalogiem

    if (!S_ISREG(file_stat.st_mode))
	return -1; // plik konfiguracyjny nie jest plikiem

    if (access(dir, X_OK) != 0)
	return -1; // nie mamy prawa zmienic katalogu

    if (access(path, R_OK) != 0)
	return -1; // nie mamy prawa odczytu pliku

    free(path);

    return 0;
}
