/*
 * Creator: Naman Dixit
 * Notice: © Copyright 2020 Naman Dixit
 */

internal_function
noreturn
void* dockerProcessLoop (void *arg)
{
    pthread_setcanceltype (PTHREAD_CANCEL_DEFERRED, NULL);

    while (true) {
        // TODO(naman): Get data
        Char *data_cmd = NULL;
        sbufPrint(data_cmd, "docker stats --no-stream --format \"{{ json . }}\" %s", (Char*)arg);
        FILE* data_file = popen(data_cmd, "r");

        fseek(data_file, 0, SEEK_END);
        long size = ftell(data_file);
        fseek(data_file, 0, SEEK_SET);
        Char *data = calloc((Size)size + 1, sizeof(*data));
        fread(data, 1, (Size)size + 1, data_file);
        fclose(data_file);

        const Char *json_error = NULL;
        cJSON *data_json = cJSON_ParseWithOpts(data, &json_error, true);

        Char *json = NULL;
        sbufPrint(json, "{\"cpu_percentage\": %f",
                  atof(cJSON_GetObjectItem(data_json, "CPUPerc")->valuestring));
        sbufPrint(json, ",\n\"memory_percentage\": %f",
                  atof(cJSON_GetObjectItem(data_json, "MemPerc")->valuestring));

        { // Memory
            Char *mem_begin = cJSON_GetObjectItem(data_json, "MemUsage")->valuestring;
            Char *mem_middle = strchr(mem_begin, '/');
            mem_middle[0] = '\0';
            mem_middle[-1] = '\0';
            mem_middle[1] = '\0';
            sbufPrint(json, ",\n\"memory_used\": \"%s\"", mem_begin);
            sbufPrint(json, ",\n\"memory_usable\": \"%s\"", mem_middle + 2);
        }

        { // Disk
            Char *block_begin = cJSON_GetObjectItem(data_json, "BlockIO")->valuestring;
            Char *block_middle = strchr(block_begin, '/');
            block_middle[0] = '\0';
            block_middle[-1] = '\0';
            block_middle[1] = '\0';
            sbufPrint(json, ",\n\"disk_read\": \"%s\"", block_begin);
            sbufPrint(json, ",\n\"disk_written\": \"%s\"", block_middle + 2);
        }

        { // Network
            Char *net_begin = cJSON_GetObjectItem(data_json, "NetIO")->valuestring;
            Char *net_middle = strchr(net_begin, '/');
            net_middle[0] = '\0';
            net_middle[-1] = '\0';
            net_middle[1] = '\0';
            sbufPrint(json, ",\n\"net_upload\": \"%s\"", net_begin);
            sbufPrint(json, ",\n\"net_download\": \"%s\"", net_middle + 2);
        }

        sbufPrint(json, "\n}\n");

        cJSON *json_parse = cJSON_Parse(json);
        Char *json_pretty = cJSON_Print(json_parse);

        Sint time_now = (Sint)time(0);
        Char *output = NULL;
        sbufPrint(output, "{\n\"message_type\": \"%s\"", "instrumentation");
        sbufPrint(output, ",\"node_id\": \"%s\"", node_name);
        sbufPrint(output, ",\n\"entity_id\": \"%s\"", (Char*)arg);
        sbufPrint(output, ",\n\"entity_type\": \"%s\"", "docker");
        sbufPrint(output, ",\n\"timestamp\": %d", time_now);
        sbufPrint(output, ",\n\"data\": %s", json_pretty);
        sbufPrint(output, "\n}\n");

        JSON_Print_Command jpc = {.msg = output,
                                  .topic = "LOG_CHANNEL"};

        cJSON_free(json_pretty);
        cJSON_Delete(json_parse);
        sbufDelete(output);
        sbufDelete(json);
        free(data);
        sbufDelete(data_cmd);

        U64 time_before = timeMilli();
        instrumentCommandEnqueue(jpc);
        U64 time_after = timeMilli();

        if ((time_after - time_before) < 1000) {
            sleep((Uint)(time_after - time_before));
        }
    }
}
