/* License: AGPLv3 or later. https://www.gnu.org/licenses/licenses.html
 * 
 * Exercise 2 - Implementing a heap (Week 3)
 * Name: Manish
 * Student Login: *****
 * 
 * Compile as:
 * $ gcc -std=c11 -Wall -o ex2 ex2.c
 */

// assert used only for testing heap property
// #include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int heap[100];
int size = 0;

void makeheap();
void shiftdown(int index);
// void shiftup(int index);
// void swap(int i, int j);
// int min(int i, int j);
// void test_heap();
// int is_bigger_or_equal(int bigger, int smaller);

int main(void)
{
    printf("Enter file name: ");
    char filename[257];
    // Assuming filename/file path won't be longer than 256 characters
    scanf("%256s", filename);

    FILE* file = fopen(filename, "r");
    if (!file)
    {
        perror(filename);
        exit(EXIT_FAILURE);
    }

    // Trailing whitespace to consume all subsequent ' ', \t, \n, \r
    while (fscanf(file, " %d ", &heap[size]) != EOF)
    {
        size++;
    }

    fclose(file);

    makeheap();
    
    // test_heap();

    // int upto = min(5, size);
    // Assuming at least 5 integers will be read (else segfault!)
    for (int i = 0; i < 5; i++)
    {
        printf("%d ", heap[i]);
    }
    printf("\n");

    return 0;
}

void makeheap()
{
    // Shiftdown Method
    int shiftdowns_required = (size / 2)-1;
    for (int i = shiftdowns_required; i >= 0; i--)
    {
        shiftdown(i);
    }

    // Shiftup method
    /*for (int i = 0; i < size; i++)
    {
       shiftup(i);
    }*/
}

void shiftdown(int index)
{
    int child;
    int temp; // used for swapping
    // Loop instead of recursion for efficiency
    while (1)
    {
        child = (index * 2) + 1;
        // Reached end of tree
        if (child >= size)
        {
            return;
        }
        // Has only one child
        if (child + 1 >= size)
        {
        }
        // Has both children
        else
        {
            // Pick the bigger child
            if (heap[child] < heap[child + 1])
            {
                child = child + 1;
            }
        }
        if (heap[index] < heap[child])
        {
            // swap
            temp = heap[index];
            heap[index] = heap[child];
            heap[child] = temp;
            
            index = child;
        }
        else
        {
            return;
        }
    }
}
/*
void shiftup(int index)
{
    int parent;
    int temp; // used for swapping
    while (1)
    {
        if (index == 0)
        {
            return;
        }
        parent = (index - 1) / 2;
        if (parent >= 0)
        {
            if (heap[parent] < heap[index])
            {
                // swap
                temp = heap[index];
                heap[index] = heap[parent];
                heap[parent] = temp;
            
                index = parent;
            }
            else
            {
                return;
            }
        }
        else
        {
            return;
        }
    }
}*/
/*
inline void swap(int i, int j)
{
    int temp = heap[i];
    heap[i] = heap[j];
    heap[j] = temp;
}*/
/*
inline int min(int i, int j)
{
    if (i < j)
    {
        return i;
    }
    return j;
}*/
/*
void test_heap()
{
    int checks_required = (size/2)+1;
    int child;
    for (int i=0; i < checks_required; i++)
    {
        // Left child
        child = (i*2)+1;
        assert(is_bigger_or_equal(i, child));
        // Right child
        assert(is_bigger_or_equal(i, ++child));
    }
}

inline int is_bigger_or_equal(int bigger, int smaller)
{
    if (bigger < size && smaller < size)
    {
        return (heap[bigger] >= heap[smaller]);
    }
    return 1;
}
*/
