#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdint.h>
#include <unistd.h>
#include <stdlib.h>

void bail();

FILE* src = NULL;
int dest = -1;
char* line = NULL;
size_t len = 0;


int main(int argc, char *argv[]){

    if (argc != 3){
        fprintf(stderr,"USAGE:\n %s source-file target-file\n", argv[0]);
        return -1;
    }
    
    // Open Source Configuration File
    src = fopen(argv[1], "r");
    if(src == NULL){
        perror("Failed to open file");
        bail();
        return -1;
    }
    
    // Open Destination File
    dest = open(argv[2], O_WRONLY);
    if(dest == -1){
        perror("Failed to open file");
        bail();
        return -1;
    }
    
    uint64_t data, addsub_mode, add_input_mode, delay, factor, timestamp;
    
    /*File Parsing Loop*/
    while(getline(&line, &len, src) != -1){
        //Check if Comment Line
        if(line[0] == '#'){
            continue;
        }
        
        if(sscanf(line, "%u %u %u %u %u", &addsub_mode, &add_input_mode, &delay, &factor, &timestamp) < 5){
            perror("Parsing of configuration file failed");
            fprintf(stderr, "Failing line: %s", line);
            bail();
            return -1;
        }
        
        data = 0x0;
        data |= ((uint64_t)0x1 << 63) | ((addsub_mode & 0x1) << 62) | ((add_input_mode & 0x1) << 61) | ((delay & 0xFF) << 40) | 
            ((factor & 0x1F) << 32) | (timestamp & 0xFFFFFFFF);
        if(write(dest, &data, sizeof(uint64_t)) != sizeof(uint64_t)){
            perror("Failed to write data");
            bail();
            return -1;
        }
    }
    
    //Write A non enabled slot
    data = 0x0;
    if(write(dest, &data, sizeof(uint64_t)) != sizeof(uint64_t)){
            perror("Failed to write data");
            bail();
            return -1;
        }
    
    //Exit safely
    bail();
    return 0;
}

void bail(){
    if(src != NULL){
        (void)fclose(src);
    }
    if(dest != -1){
        (void)close(dest);
    }
    if(line != NULL){
        free(line);
    }
}
