#include <ftw.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <stdbool.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <dirent.h>
#include <errno.h>

#define MAX_EXTENSIONS 6
#define MAX_PATH_LENGTH 256

char extensions[MAX_EXTENSIONS][10]; // Array to store extensions
int extensionCount = 0; // Count of extensions

char sourcePath[MAX_PATH_LENGTH];
char destinationPath[MAX_PATH_LENGTH];
bool copyModeSelected;

bool hasExcludedExtension(const char *filename) {
    if (extensionCount == 0)
        return false;

    for (int i = 0; i < extensionCount; i++) {
        const char *extension = extensions[i];
        int filenameLength = strlen(filename);
        int extensionLength = strlen(extension);

        if (filenameLength >= extensionLength) {
            const char *fileExtension = filename + (filenameLength - extensionLength);
            if (strcmp(fileExtension, extension) == 0)
                return true;
        }
    }

    return false;
}

void handleError(const char *errorMessage) {
    perror(errorMessage);
    exit(1);
}

void copyOrMoveFile(const char *source, const char *destination) {
    if (copyModeSelected) {
        if (link(source, destination) != 0) {
            handleError("Error while copying file");
        }
    } else {
        if (rename(source, destination) != 0) {
            handleError("Error while moving file");
        }
    }
}

void createDirectory(const char *path, mode_t mode) {
    if (mkdir(path, mode) != 0 && errno != EEXIST) {
        handleError("Error while creating directory");
    }
}

void removeFile(const char *path) {
    if (unlink(path) != 0) {
        handleError("Error while removing file");
    }
}

void removeDirectory(const char *path) {
    DIR *dir = opendir(path);
    if (dir == NULL) {
        handleError("Error opening directory");
    }

    struct dirent *entry;
    while ((entry = readdir(dir)) != NULL) {
        if (strcmp(entry->d_name, ".") != 0 && strcmp(entry->d_name, "..") != 0) {
            char subpath[MAX_PATH_LENGTH];
            snprintf(subpath, MAX_PATH_LENGTH, "%s/%s", path, entry->d_name);

            if (entry->d_type == DT_DIR) {
                removeDirectory(subpath);
                rmdir(subpath); // Remove the empty directory
            } else {
                removeFile(subpath);
            }
        }
    }

    closedir(dir);
}


int processFile(const char *filePath, const struct stat *sb, int fileType, struct FTW *ftwbuf) {
    char destinationLocation[MAX_PATH_LENGTH];
    snprintf(destinationLocation, MAX_PATH_LENGTH, "%s/%s", destinationPath, filePath + strlen(sourcePath) + 1);

    if (fileType == FTW_F) {
        if (!hasExcludedExtension(filePath)) {
            copyOrMoveFile(filePath, destinationLocation);
        }
    } else if (fileType == FTW_D) {
        createDirectory(destinationLocation, sb->st_mode);
    }

    return 0;
}

void parseArguments(int argc, char *argv[]) {
    if (argc < 4) {
        printf("Usage: ncpmvdir [SourcePath] [DestinationPath] [options]\n");
        printf("Options:\n");
        printf("-cp: Copy mode | -mv: Move mode\n");
        printf("[Extension]: Exclude files with the specified extension\n");
        exit(1);
    } else {
        if ((strcmp(argv[3], "-cp") == 0) || (strcmp(argv[3], "-CP") == 0)) {
            copyModeSelected = true;
        } else if ((strcmp(argv[3], "-mv") == 0) || (strcmp(argv[3], "-MV") == 0)) {
            copyModeSelected = false;
        } else {
            printf("Option should be of type -cp or -mv\n");
            exit(1);
        }
        if (argc > 4) {
            for (int i = 4; i < argc; i++) {
                if (extensionCount >= MAX_EXTENSIONS) {
                    printf("Too many extensions specified\n");
                    exit(1);
                }
                strncpy(extensions[extensionCount], argv[i], 10);
                extensionCount++;
            }
        }
    }

    strncpy(sourcePath, argv[optind], MAX_PATH_LENGTH);
    strncpy(destinationPath, argv[optind + 1], MAX_PATH_LENGTH);
}

void traverseFileTree(const char *sourcePath) {
    if (nftw(sourcePath, processFile, 20, FTW_NS) != 0) {
        handleError("Error while traversing file tree");
    }
}

int main(int argc, char *argv[]) {
    parseArguments(argc, argv);
    traverseFileTree(sourcePath);

    if (!copyModeSelected) {
        removeDirectory(sourcePath);
    }

    return 0;
}


refactor this code in such a way that the output code becomes a whole new code with different strcuture, heirarchy, diff function and variable names, diff print statements, but note that the logic and functionalities of the code should remian the same