/**
 * This file group all function which interact with data structure
 */

#ifndef _DATA
#define _DATA

#include "prototype.h"

#include <unistd.h>

/**
 * Take array and lengh and fill it with character '\0'
 * <b>Returned array should be</b> free
 */
char *new_array(size_t size)
{
    char *arr = (char *)malloc(size * sizeof(char) + 1);
    if (arr == NULL)
    {
        error("fatal : failed to alloc array");
    }
    // fill allocated array with '\0'
    init_array(arr, size);
    return arr;
}

void init_array(char *arr, size_t size)
{
    for (size_t i = 0; i < size; i++)
    {
        arr[i] = '\0';
    }
}

/**
 * Read file descriptor without already defined size
 * <b>Returned array should be</b> free
 */
char *read_infinite_fd(int fd)
{
    int batch_size = 1024;
    char *stdout_buffer = new_array(batch_size);

    // copy read pipefd to buffer
    int already_read = read(fd, stdout_buffer, batch_size);
    int current_read = 0;
    do
    {
        already_read += current_read;
        char *stdout_buffer_temp = (char *)realloc(stdout_buffer, already_read + batch_size * sizeof(char));
        // if realloc faile davoid memory leak free primary pointer
        if (stdout_buffer_temp == NULL)
        {
            free(stdout_buffer);
            error("fatal : failed to realloc during pipe child reading");
        }
        else
        {
            stdout_buffer = stdout_buffer_temp;
            // fill new allocated part with '\0'
            init_array(stdout_buffer + already_read, batch_size);
        }

        current_read = 0;
    } while ((current_read = read(fd, stdout_buffer + already_read, batch_size)) != 0);

    return stdout_buffer;
}

/**
 * Read stdin and write to file descriptor
 */
void write_infinite_fd(int fd)
{
    char *stdin_buffer = new_array(1024);
    int x = 0;
    printf("$ ");
    fflush(stdout);

    while ((x = read(STDIN_FILENO, stdin_buffer, sizeof(stdin_buffer))) > 0)
    {
        write(fd, stdin_buffer, sizeof(stdin_buffer));
        init_array(stdin_buffer, sizeof(stdin_buffer));
        printf("$ ");
        fflush(stdout);
    }
    free(stdin_buffer);
}

/**
 * Function use to filter char* array
 * copy src char* into dst if function is true
 * Return dst length
 */
int filter_char_array(int src_length, char **src, char **dst, char_predicate filter_func)
{
    int dst_size = 0;
    for (int i = 0; i < src_length; i++)
    {
        if ((*filter_func)(src[i]))
        {
            dst[dst_size] = src[i];
            dst_size++;
        }
    }
    return dst_size;
}

#endif
