#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <math.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/select.h>
#include <fcntl.h>
#include "error.h"

#define SLAVE_NUM 1
#define MAX_SIZE 200

void create(int ans[2], int pipes[SLAVE_NUM][2]);

int main(int argc, char *argv[]) {
    //setvbuf(stdout, NULL, _IONBF, 0);

    if (argc == 1)
        printError("Error: no arguments provided");

    int ans[2];
    int pipes[SLAVE_NUM][2];
    create(ans, pipes);
    //sleep(1);

    fd_set ansSet;
    FD_ZERO(&ansSet);
    FD_SET(ans[0], &ansSet);
    //printf("%d", ansSet);

    fd_set fdSet;
    FD_ZERO(&fdSet);
    int n = 0;
    for (; n < SLAVE_NUM; n++)
        FD_SET(pipes[n][1], &fdSet);

    int flag = 0, j = 0;
    struct stat statBuf;
    int i = 1;
    for (; i < argc; i++) {
        if (stat(argv[i], &statBuf) == -1)
            printSystemError("Error, one of the specified paths is incorrect");

        if (!S_ISREG(statBuf.st_mode))
            continue;

        if (j == SLAVE_NUM) {
            j = 0;
            flag = 1;
        }
        if (!flag) {

            if (write(pipes[j++][1], argv[i], strlen(argv[i]) + 1) < 0) {
            //if (write(pipes[j++][1], "prueba.cnf\n", strlen(argv[i]) + 1) < 0) {
                printf("quesesto %d\n", fcntl(pipes[j-1][1], F_GETFD));
                printf("%s\n", argv[i]);
                printf("fd write: %d\n", pipes[j-1][0]);
                printSystemError("write() -- ERROR");
            }
            //close(pipes[j-1][1]);
        } else {
            int fd;
            if ((fd = select(5, &fdSet, NULL, NULL, NULL) < 0))
                printSystemError("select() -- ERROR");
            char buf[MAX_SIZE];
            if (read(fd, buf, MAX_SIZE) < 0)
                printSystemError("read() -- ERROR");
            printf("%s", buf);
            int k = 0;
            for (; i < SLAVE_NUM; k++) {
                if (pipes[k][1] == fd) {
                    if (write(pipes[k][1], argv[i], strlen(argv[i])) < 0)
                        printSystemError("write() -- ERROR");
                    continue;
                }
            }
        }
    }

    int fd;
    char buf[MAX_SIZE];
    if ((fd = select(4, &ansSet, NULL, NULL, NULL)) < 0)
        printSystemError("select() -- ERROR");
    int readBytes = 0;
    do {
        if ((readBytes += read(ans[0], buf + readBytes, MAX_SIZE)) < 0)
            printSystemError("read() -- ERROR");
    } while (buf[readBytes - 1] != '\n');
    buf[readBytes] = 0;
    printf("%s\n", buf);
    //write(pipes[j++][1], "prueba.cnf\n", strlen(argv[i]) + 1);
        /*
        readBytes = 0;
        do {
            if ((readBytes += read(ans[0], buf + readBytes, MAX_SIZE)) < 0)
                printSystemError("read() -- ERROR");
        } while (buf[readBytes - 1] != '\n');
        buf[readBytes] = 0;
        printf("%s\n", buf);
        */
}

void create(int ans[2], int pipes[5][2]) {
    pid_t pid[SLAVE_NUM];
    if (pipe(ans) < 0)
        printSystemError("pipe() -- ERROR");

    int i = 0;
    for (; i < SLAVE_NUM; i++) {
        if (pipe(pipes[i]) < 0)
            printSystemError("pipe() -- ERROR");
        if ((pid[i] = fork()) == 0) {
            if (close(ans[0]) < 0)
                printSystemError("close() -- ERROR");
            if (dup2(ans[1], STDOUT_FILENO) < 0)
                printSystemError("dup2() -- ERROR 1");
            if (close(ans[1]) < 0)
                printSystemError("close() -- ERROR");

            if (close(pipes[i][1]) < 0)
                printSystemError("close() -- ERROR");
            if (dup2(pipes[i][0], STDIN_FILENO) < 0)
                printSystemError("dup2() -- ERROR 2");
            if (close(pipes[i][0]) < 0)
                printSystemError("close() -- ERROR");

            if (execv("slave.o", NULL) < 0)
                printSystemError("execv() -- ERROR");
        }
        else if (pid[i] < 0)
            printSystemError("fork() -- ERROR");

        if (close(pipes[i][0]) < 0)
            printSystemError("close() -- ERROR");
    }

    if (close(ans[1]) < 0)
        printSystemError("close() -- ERROR");
}