/*
 *	BORING COPYRIGHT NOTICE:
 *
 *	This file is a heavily modified version of the priority queue found
 *	in the Apache project and the libpqueue library.
 *
 *		https://github.com/vy/libpqueue
 *
 *	These are the original authors:
 *
 *		Copyright 2010 Volkan Yazıcı <volkan.yazici@gmail.com>
 *		Copyright 2006-2010 The Apache Software Foundation
 *
 *  This file is licensed under the Apache 2.0 license, which 
 *  supposedly makes it compatible with the GPLv2 that libgit2 uses.
 *
 *  Check the Apache license at:
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 *  So much licensing trouble for a binary heap. Oh well.
 */

#include "common.h"
#include "pqueue.h"

#define left(i)   ((i) << 1)
#define right(i)  (((i) << 1) + 1)
#define parent(i) ((i) >> 1)

int git_pqueue_init(git_pqueue *q, size_t n, git_pqueue_cmp cmppri)
{
	assert(q);

    /* Need to allocate n+1 elements since element 0 isn't used. */
    if ((q->d = malloc((n + 1) * sizeof(void *))) == NULL)
		return GIT_ENOMEM;

    q->size = 1;
    q->avail = q->step = (n + 1);  /* see comment above about n+1 */
    q->cmppri = cmppri;

    return GIT_SUCCESS;
}


void git_pqueue_free(git_pqueue *q)
{
    free(q->d);
	q->d = NULL;
}

void git_pqueue_clear(git_pqueue *q)
{
	q->size = 1;
}

size_t git_pqueue_size(git_pqueue *q)
{
    /* queue element 0 exists but doesn't count since it isn't used. */
    return (q->size - 1);
}


static void bubble_up(git_pqueue *q, size_t i)
{
    size_t parent_node;
    void *moving_node = q->d[i];

    for (parent_node = parent(i);
         ((i > 1) && q->cmppri(q->d[parent_node], moving_node));
         i = parent_node, parent_node = parent(i)) {
        q->d[i] = q->d[parent_node];
    }

    q->d[i] = moving_node;
}


static size_t maxchild(git_pqueue *q, size_t i)
{
    size_t child_node = left(i);

    if (child_node >= q->size)
        return 0;

    if ((child_node + 1) < q->size &&
        q->cmppri(q->d[child_node], q->d[child_node + 1]))
        child_node++; /* use right child instead of left */

    return child_node;
}


static void percolate_down(git_pqueue *q, size_t i)
{
    size_t child_node;
    void *moving_node = q->d[i];

    while ((child_node = maxchild(q, i)) != 0 &&
           q->cmppri(moving_node, q->d[child_node])) {
        q->d[i] = q->d[child_node];
        i = child_node;
    }

    q->d[i] = moving_node;
}


int git_pqueue_insert(git_pqueue *q, void *d)
{
    void *tmp;
    size_t i;
    size_t newsize;

    if (!q) return 1;

    /* allocate more memory if necessary */
    if (q->size >= q->avail) {
        newsize = q->size + q->step;
        if ((tmp = realloc(q->d, sizeof(void *) * newsize)) == NULL)
            return GIT_ENOMEM;

        q->d = tmp;
        q->avail = newsize;
    }

    /* insert item */
    i = q->size++;
    q->d[i] = d;
    bubble_up(q, i);

    return GIT_SUCCESS;
}


void *git_pqueue_pop(git_pqueue *q)
{
    void *head;

    if (!q || q->size == 1)
        return NULL;

    head = q->d[1];
    q->d[1] = q->d[--q->size];
    percolate_down(q, 1);

    return head;
}


void *git_pqueue_peek(git_pqueue *q)
{
    if (!q || q->size == 1)
        return NULL;
    return q->d[1];
}
