#include <merge.h>
#include <stdio.h>
#include "chunk.h"


CHUNK_Iterator CHUNK_CreateIterator(int fileDesc, int blocksInChunk) {
    CHUNK_Iterator iterator;

    iterator.file_desc = fileDesc;
    iterator.current = 1;  // Initialize the iterator to point to the first block.
    iterator.lastBlocksID = HP_GetIdOfLastBlock(fileDesc);  // Get the last block ID in the file.
    iterator.blocksInChunk = blocksInChunk;

    return iterator;
}

int CHUNK_GetNext(CHUNK_Iterator *iterator, CHUNK *chunk) {
    // Calculate the last block ID to consider in this iteration
    int lastBlockToConsider = iterator->current + iterator->blocksInChunk - 1;
    
    // Check if there are more blocks to iterate over
    if (iterator->current <= iterator->lastBlocksID) {
        chunk->file_desc = iterator->file_desc;
        chunk->from_BlockId = iterator->current;
        
        // Ensure that to_BlockId does not exceed the last block ID
        chunk->to_BlockId = (lastBlockToConsider <= iterator->lastBlocksID) ? lastBlockToConsider : iterator->lastBlocksID;

        // Calculate the number of records and blocks in the chunk
        chunk->recordsInChunk = 0;
        for (int blockId = chunk->from_BlockId; blockId <= chunk->to_BlockId; ++blockId) {
            chunk->recordsInChunk += HP_GetRecordCounter(iterator->file_desc, blockId);
        }
        
        // Calculate blocksInChunk based on from_BlockId and to_BlockId
        chunk->blocksInChunk = chunk->to_BlockId - chunk->from_BlockId + 1;

        // Update iterator state for the next iteration
        iterator->current = chunk->to_BlockId + 1;

        return 1; // Success
    } else {
        // No more blocks to iterate
        return 0;
    }
}

int CHUNK_GetIthRecordInChunk(CHUNK *chunk, int i, Record *record) {
    // Check if i is a valid index within the recordsInChunk range
    if (i >= 0 && i < chunk->recordsInChunk) {
        // Calculate the block and cursor position for the i-th record
        int blockId = chunk->from_BlockId + (i / HP_GetMaxRecordsInBlock(chunk->file_desc));
        int cursor = i % HP_GetMaxRecordsInBlock(chunk->file_desc);

        // Retrieve the record from the heap file
        if (HP_GetRecord(chunk->file_desc, blockId, cursor, record) == -1) {
            // Record retrieval failed
            HP_Unpin(chunk->file_desc, blockId);
            return -1;
        }

        // Unpin the block after using the record
        HP_Unpin(chunk->file_desc, blockId);

        // Record retrieval successful
        return 0;
    } else {
        // Invalid index
        return -1;
    }
}


int CHUNK_UpdateIthRecord(CHUNK *chunk, int i, Record record) {
    // Check if i is a valid index within the recordsInChunk range
    if (i >= 0 && i < chunk->recordsInChunk) {
        // Calculate the block and cursor position for the i-th record
        int blockId = chunk->from_BlockId + (i / HP_GetMaxRecordsInBlock(chunk->file_desc));
        int cursor = i % HP_GetMaxRecordsInBlock(chunk->file_desc);

        // Update the record in the heap file
        if (HP_UpdateRecord(chunk->file_desc, blockId, cursor, record) == -1) {
            // Record update failed
            HP_Unpin(chunk->file_desc, blockId);
            return -1;
        }

        // Unpin the block after updating the record
        HP_Unpin(chunk->file_desc, blockId);

        // Record update successful
        return 0;
    } else {
        // Invalid index
        return -1;
    }
}

void CHUNK_Print(CHUNK chunk) {
    printf("Printing records in CHUNK:\n");

    // Iterate through records in the chunk
    for (int i = 0; i < chunk.recordsInChunk; ++i) {
        Record record;

        // Retrieve the i-th record in the chunk
        if (CHUNK_GetIthRecordInChunk(&chunk, i, &record) == 0) {
            // Print the record details using the printRecord function
            printf("Record %d: ", i + 1);
            printRecord(record);
        } else {
            // Handle record retrieval failure
            printf("Failed to retrieve record %d in the chunk.\n", i + 1);
        }
    }
}

CHUNK_RecordIterator CHUNK_CreateRecordIterator(CHUNK *chunk) {
    CHUNK_RecordIterator iterator;

    // Check if the chunk pointer is NULL
    if (chunk == NULL) {
        // Handle the case of a NULL pointer (e.g., log an error, return a default iterator, etc.)
        // For simplicity, let's set the iterator properties to default values
        iterator.chunk.file_desc = -1;
        iterator.chunk.from_BlockId = -1;
        iterator.chunk.to_BlockId = -1;
        iterator.chunk.recordsInChunk = 0;
        iterator.chunk.blocksInChunk = 0;
        iterator.currentBlockId = -1;
        iterator.cursor = -1;
        return iterator;
    }

    // Initialize iterator properties
    iterator.chunk = *chunk; // Copy the CHUNK structure
    iterator.currentBlockId = chunk->from_BlockId;
    iterator.cursor = 0;

    return iterator;
}

int CHUNK_GetNextRecord(CHUNK_RecordIterator *iterator,Record* record){
    
}