//-----------------------------------------------------------------------------
// generateConfig.c
//
// generate and store a binary config file
//
// Group: Group 00, study assistants
//
// Authors: prog-tutors
//
// Latest Changes: 2009/08/12, created all
//----------------------------------------------------------------------------

//includes
#include <stdio.h>
#include <stdlib.h>

//defines
//#define ENABLE_DEBUG  //uncomment to enable debug messages
#define NUM_CONFIGS_TO_WRITE 1
#define DEFAULT_CONFIG_PATH "tc1.cfg"

//returncodes
#define ERROR_NO_MEMORY -3
#define ERROR_FILE_NOT_READ -2
#define ERROR_CONFIG_CORRUPTED -1
#define SUCCESSFUL 0

//typedefs
typedef struct
{
  int x_coord;
  int y_coord;
} Coord;

typedef struct
{
  char hello_char[5];
  int offset_x;
  Coord start_pos;
} Config;

//forwarders
int generateConfigFile(int offset_x, int start_x, int start_y, char* path);
int readConfigFile(char* path, Config* return_config);
int printConfigFile(Config* config_to_print);
void copystrToCharArray(char* str_dest, char* str_source);

//----------------------------------------------------------------------------
///
/// mainfunction
///
/// writes a config file & prints the content to the screen
///
/// @param: -f=[path to config]    if param not set, tc1.cfg will be used
int main(int argc, char* argv[])
{
  int return_code = SUCCESSFUL;
  Config* read_config;
  Config* backup_read_config;
  char* path_to_read_from = DEFAULT_CONFIG_PATH;
  
  //get path if config param set
  if(argc > 1)
  {
    //if(strncmp(argv[1], "-f=", 3) == 0) //if using string.h
    if(argv[1][0] == '-' && argv[1][1] == 'f' && argv[1][2] == '=')
    {
      path_to_read_from = &argv[1][3];
    }
  }
  
  //write configs
  return_code = generateConfigFile(10, 100, 1000, path_to_read_from);
  printf("TC1 wrote %d block(s) \n", return_code);
  
  //prepare to read config
  read_config = malloc(NUM_CONFIGS_TO_WRITE * sizeof(Config));
  if(read_config == NULL)
  {
    return ERROR_NO_MEMORY;
  }

  //read to verify
  backup_read_config = read_config;
  return_code = readConfigFile(path_to_read_from, read_config);
  if(read_config == NULL)
  {
    free(backup_read_config);
    return ERROR_CONFIG_CORRUPTED;
  }
  printConfigFile(read_config);

  //cleanup
  free(read_config);

  return 0;
};

//----------------------------------------------------------------------------
///
/// generateConfigFile
/// writes a binary config file
///
/// @param int offset_x:  start offset
/// @param int start_x:   pos to start, x coord
/// @param int start_y:   pos to start, y coord
/// @param char* path:    path to store config file
///
/// @return 0 in case of success otherwise -1
//
int generateConfigFile(int offset_x, int start_x, int start_y, char* path)
{
  Config* first_config;
  FILE* config_file;
  int file_access_return = 0;
  Coord startpoint;

  first_config = malloc(NUM_CONFIGS_TO_WRITE * sizeof(Config));
  if(first_config == NULL)
  {
    return ERROR_NO_MEMORY;
  }

  //use string functions(#include <string.h> if used)
  //strcpy(first_config->hello_char, "hello");  //keep in mind string != char Array!
  
  startpoint.x_coord = start_x;
  startpoint.y_coord = start_y;
   
  copystrToCharArray(first_config->hello_char, "hello");
  first_config->offset_x = offset_x;
  first_config->start_pos = startpoint;

  config_file = fopen(path, "wb");
  file_access_return = fwrite(first_config, sizeof(Config), NUM_CONFIGS_TO_WRITE, config_file);
  printf("wrote configs: %d\n", file_access_return);
  if(file_access_return != NUM_CONFIGS_TO_WRITE)
  {
    fclose(config_file);
    free(first_config);
    return ERROR_CONFIG_CORRUPTED;
  }

  fclose(config_file);
  free(first_config);
  
  printf("wrote to file: %s\n", path);

  return file_access_return;
};

//----------------------------------------------------------------------------
///
/// readConfigFile
/// reads a binary config file into struct Config
///
/// @param char* path:              path to read config file from
/// @param Config* return_config:   place to store read configuration
///
/// @return int:                    Errorcode SUCCESSFULL or ERROR_FILE_NOT_READ
//
int readConfigFile(char* path, Config* return_config)
{
  FILE* config_file_to_read;

  config_file_to_read = fopen(path,"rb");
  if(config_file_to_read != NULL)
  {
    fread(return_config, sizeof(Config), NUM_CONFIGS_TO_WRITE, config_file_to_read);
    fclose(config_file_to_read);
    return SUCCESSFUL;
  }

  //if config could not be read
  return ERROR_FILE_NOT_READ;
};

//----------------------------------------------------------------------------
///
/// printConfigFile
/// displays the content of a config struct
///
/// @param Config* config_to_print: config to print content
///
/// @return int: errorcode
///
//
int printConfigFile(Config* config_to_print)
{
  if(config_to_print == NULL)
  {
     return ERROR_CONFIG_CORRUPTED;
  }

  printf("--Config--\n");
  printf("hello:  %s\n", config_to_print->hello_char); //probably not working, why?
  printf("hello:  %c%c%c%c%c\n",
                                config_to_print->hello_char[0],
                                config_to_print->hello_char[1],
                                config_to_print->hello_char[2],
                                config_to_print->hello_char[3],
                                config_to_print->hello_char[4]
        );
  printf("start:  <%d,%d>\n", config_to_print->start_pos.x_coord,
                              config_to_print->start_pos.y_coord
        );
  printf("offset: %d\n", config_to_print->offset_x);        
  printf("\n");

  return SUCCESSFUL;
};

//----------------------------------------------------------------------------
///
/// copystrToCharArray
/// copy string from source to dest
/// very similar to strcpy
///
/// @param char* str_dest:   destination to write string
/// @param char* str_source: source to read string from
///
/// @return void
///
//
void copystrToCharArray(char* str_dest, char* str_source)
{
  int count_pos = 0;
  while(str_source[count_pos] != '\0')
  {
    #ifdef ENABLE_DEBUG
      printf("%d: %d = %c ", count_pos, str_source[count_pos],
                             str_source[count_pos]);
    #endif
    str_dest[count_pos] = str_source[count_pos];
    count_pos++;
  }
  #ifdef ENABLE_DEBUG
    printf("\n");
    printf("src  %d: %d = %c \n", count_pos, str_source[count_pos], 
                                str_source[count_pos]);
    printf("dest %d: %d = %c \n", count_pos, str_dest[count_pos],
                                str_dest[count_pos]);
  #endif  
}

