#include <stdlib.h>
#include <stdio.h>
#include <assert.h>

#include "job_queue.h"

pthread_mutex_t queue_operation = PTHREAD_MUTEX_INITIALIZER;
pthread_mutex_t queue_push = PTHREAD_MUTEX_INITIALIZER;
pthread_mutex_t queue_pop = PTHREAD_MUTEX_INITIALIZER;
pthread_mutex_t queue_destroy = PTHREAD_MUTEX_INITIALIZER;

int job_queue_init(struct job_queue *job_queue, int capacity) {
    pthread_mutex_lock(&queue_operation);
    pthread_mutex_lock(&queue_push);
    pthread_mutex_lock(&queue_pop);
    pthread_mutex_lock(&queue_destroy);

    job_queue->capacity = capacity;
    job_queue->size = 0;
    job_queue->jobs = malloc(capacity);

    pthread_mutex_unlock(&queue_operation);
    pthread_mutex_unlock(&queue_push);
    pthread_mutex_unlock(&queue_destroy);
    return 0;
}

int job_queue_destroy(struct job_queue *job_queue) {
    printf("esauc\n");
    pthread_mutex_lock(&queue_destroy);
    pthread_mutex_lock(&queue_operation);

    printf("esauc\n");
    //free(job_queue->jobs);
    printf("esauc\n");
    //free(job_queue);
    printf("esauc\n");

    pthread_mutex_unlock(&queue_push);
    pthread_mutex_unlock(&queue_pop);
    pthread_mutex_unlock(&queue_destroy);
    pthread_mutex_unlock(&queue_operation);
    return 0;
}

int job_queue_push(struct job_queue *job_queue, void *data) {
    pthread_mutex_lock(&queue_push);
    pthread_mutex_lock(&queue_operation);

    (&job_queue->jobs)[job_queue->size] = data;
    job_queue->size = job_queue->size + 1;

    if (job_queue->size != job_queue->capacity) {
        pthread_mutex_unlock(&queue_push);
    }

    if (job_queue->size == 1) {
        pthread_mutex_unlock(&queue_pop);
        pthread_mutex_lock(&queue_destroy);
    }

    pthread_mutex_unlock(&queue_operation);
    return 0;
}

int job_queue_pop(struct job_queue *job_queue, void **data) {
    pthread_mutex_lock(&queue_pop);
    pthread_mutex_lock(&queue_operation);

    if (job_queue == NULL) {
        pthread_mutex_unlock(&queue_pop);
        pthread_mutex_unlock(&queue_operation);
        return -1;
    }

    job_queue->size = job_queue->size - 1;
    *data = (&job_queue->jobs)[job_queue->size];

    if (job_queue->size == 0) {
        pthread_mutex_unlock(&queue_destroy);
    }

    if (job_queue->size != 0) {
        pthread_mutex_unlock(&queue_pop);
    }

    if (job_queue->size == job_queue->capacity - 1) {
        pthread_mutex_unlock(&queue_pop);
    }

    pthread_mutex_unlock(&queue_operation);
    return 0;
}
