//Insert the exact field of each record into the indexing
t_rc SSQLM_Manager::InsertIndexEntries(REM_RecordFileHandle &rfh, int attrOffset/*, INXM_IndexHandle ih*/) {
	t_rc rc;
	int numReservedPages = rfh.sfh.GetNumReservedPages();
	int numberofSlots = rfh.rfsh.nrecords;

	REM_RecordID rid;
	REM_RecordHandle rh;
	int slot = 0;
	int pageID = 2;
	char *data;

	if(numReservedPages < 2)
		return SSQLM_NOENTRYTOINDEX;

	if(numberofSlots == 0)
		return SSQLM_NOENTRYTOINDEX;

	for( ; pageID <= numReservedPages; pageID++) {
		for( ; slot <= rfh.rfsh.recordsPerPage; slot++) {
			if(slot >(rfh.rfsh.nrecords - 1))
				return OK;

			rc = rid.SetPageID(pageID);
			if(rc != OK)
				return rc;

			rc = rid.SetSlot(slot);
			if(rc != OK)
				return rc;

			rc = rfh.ReadRecord(rid, rh);
			if(rc != OK)
				return rc;

			rc = rh.GetData(data);
			if(rc != OK)
				return rc;

			/*rc = ih.InsertEntry(data[attrOffset], rid);
			if(rc != OK)
				return rc;
*/
		}
	}
}
t_rc SSQLM_Manager::CompareAttributes(t_attrInfo comparisonAttribute, t_attrInfo convertionAttribute, t_compOp compOp, vector<char *> &pData) {
	t_rc rc;
	REM_RecordFileHandle rfhCompare;
	REM_RecordFileHandle rfhConvertion;
	REM_RecordHandle rhCompare;
	REM_RecordHandle rhConvertion;
	REM_RecordID ridCompare;
	REM_RecordID ridConvertion;
	if(comparisonAttribute.indexNo != -1) {
		/*INXM_IndexHandle indesHandle;
		INXM_IndexScan indexScan;
		

		std::stringstream ss;
		ss << comparisonAttribute.relName << "." << comparisonAttribute.indexNo;
		
		rc = inxm.OpenIndex(ss.str(), comparisonAttribute.indexNo, indexHandle);
		if(rc != OK)
			return rc;

		rc = indexScan.OpenIndexScan(indexHandle, compOp, 

*/

	}else {
		if(comparisonAttribute.relName != convertionAttribute.relName) {
			rc = rfm.OpenRecordFile(comparisonAttribute.relName, rfhCompare);
			if(rc != OK)
				return rc;
			rc = rfm.OpenRecordFile(convertionAttribute.relName, rfhConvertion);
			if(rc != OK)
				return rc;

			REM_RecordFileScan fileScan;
		
			int slotCompare = 0;
			int pageIDCompare = 2;
			int slotConvertion = 0;
			int pageIDConvertion = 2;

			for( ;pageIDCompare <= rfhCompare.sfh.GetNumReservedPages(); pageIDCompare++) {
				for( ;slotCompare <= rfhCompare.rfsh.nrecords; slotCompare++) {
					rc = ridCompare.SetPageID(pageIDCompare);
					if(rc != OK)
						return rc;
					
					rc = ridCompare.SetSlot(slotCompare);
					if(rc != OK)
						return rc;

					rc = rfhCompare.ReadRecord(ridCompare, rhCompare);
					if(rc != OK)
						return rc;

					char *dataCompare;
					rc = rhCompare.GetData(dataCompare);
					if(rc != OK)
						return rc;

					rc = fileScan.OpenRecordScan(rfhConvertion, convertionAttribute.attrType, convertionAttribute.attrLength, convertionAttribute.offset, compOp, dataCompare);
					if(rc != OK)
						return rc;

					char *dataConvertion;
					while(fileScan.GetNextRecord(rhConvertion) == OK){
						rc = rhConvertion.GetData(dataConvertion);
						if(rc != OK)
							return rc;

						pData.push_back(dataCompare);
						pData.push_back(dataConvertion);
					}
					fileScan.CloseRecordScan();
				}
			}
		}
	}
	return OK;
}
t_rc REM_RecordFileHandle::InsertRecord(const char *pData, REM_RecordID &rid)	{
                                                                                         // If file is open.  
	if (!this->is_open) { return REM_FHCLOSED; }
	t_rc rc;
	
                                                                                        // Find an empty page to write the new record. 
	STORM_PageHandle target_page;
	REM_PageHeader page_header = {0};                                               // We store 0 ,we haven't any record yet.
	char *page_data;
	
                                                                                        //If there is no free space on this page we reserve a new page. 
	if (this->rem_file_header.is_last_page_full) {
		
		rc = sfh.ReservePage(target_page);                                      // Reserve the new page.
		if (rc != OK) { return rc; }
		
                                                                                        // We mark the last page as not full. 
		this->rem_file_header.is_last_page_full = false;
		
                                                                                        // Update file header and mark it as dirty. 
		memcpy(this->pData_fileHeader, &this->rem_file_header, REM_FILEHEADER_SIZE);

		rc = this->sfh.MarkPageDirty(this->page_num_file_header);
		if (rc != OK) { return rc; }
		
                                                                                         // Get a pointer to the data of the new page to write data. 	
		rc = target_page.GetDataPtr(&page_data);
		if (rc != OK) { return rc; }
				
	}
                                                                                	// If we have free space in a page, we just get the page. 
	else {
		rc = this->sfh.GetLastPage(target_page);
		if (rc != OK) { return rc; }
		
                                                                                        // Get a pointer to the data of the the page to read the REM Page Header. 
		rc = target_page.GetDataPtr(&page_data);
		if (rc != OK) { return rc; }
		
		memcpy(&page_header, page_data, REM_PAGEHEADER_SIZE);
                
		
	}
	
                                                                                        //We calculate the corect offset(page header size + the offset) of each record there and we place the data 

	memcpy(&page_data[REM_PAGEHEADER_SIZE+(page_header.n_records*this->rem_file_header.record_size)], pData, this->rem_file_header.record_size);
	page_header.n_records+=1;
        this->rem_file_header.n_records+=1;
        memcpy(this->pData_fileHeader, &this->rem_file_header, REM_FILEHEADER_SIZE);
        rc = this->sfh.MarkPageDirty(this->page_num_file_header);
		if (rc != OK) { return rc; }
                                                                                        // Increase the number of records in the page header. This number is also the slot number of the record. 
	int slot_num = page_header.n_records; 
                                                                                	// Declare page number we are currently working on. 
	int page_num;
	rc = target_page.GetPageID(page_num);
	if (rc != OK) { return rc; }
	
                                                                                        //If page is full. 
	if (page_header.n_records == this->rem_file_header.records_per_page) {
		this->rem_file_header.is_last_page_full = true;
		
                                                                                        // Update the file header and mark as dirty. 
		memcpy(this->pData_fileHeader, &this->rem_file_header, REM_FILEHEADER_SIZE);
		
		rc = this->sfh.MarkPageDirty(this->page_num_file_header);
		if (rc != OK) { return rc; }
		
                                                                                        // Get a pointer to the data of the new page to write the new data. 	
		rc = target_page.GetDataPtr(&page_data);
		if (rc != OK) { return rc; }		
	}
	
                                                                                        // Write the new REM Page Header. 
	memcpy(page_data, &page_header, REM_PAGEHEADER_SIZE);
	
	
                                                                                        // Mark the page as dirty because we modified it 
	rc = this->sfh.MarkPageDirty(page_num);
	if (rc != OK) { return rc; }
	
	this->sfh.FlushPage(page_num);                                                  // We are flushing pages
	
                                                                                        // Unpin the page 
	rc = this->sfh.UnpinPage (page_num);
	if (rc != OK) { return rc; }
	
                                                                                        // Set the passed RID's page and slot number 
	rc = rid.SetPageID(page_num);
	if (rc != OK) { return rc; }
	rc = rid.SetSlot(slot_num);
	if (rc != OK) { return rc; }

		
	return (OK);
}
t_rc REM_RecordFileHandle::InsertRecord(const char *pData, REM_RecordID &rid) {

    //Edit
    if(!open) return REM_HANDLE_IS_CLOSED;

    int numReservedPages=fh.GetNumReservedPages(); //πλήθος των reserved pages
    int i;
    this->pData=pData; //δεδομένα που θα βάλουμε στην εγγραφή.
    int pageID = 0; //ID της σελίδας όπου θα βάλουμε δεδομένα.
    char *pageData; //δεδομένα της σελίδας όπου θα βάλουμε την εγγραφή.
    for(i=0; i<numReservedPages; i++)
    {

        rc=	fh.GetNextPage(pageID,ph);
        if(rc!=OK) return rc;

        rc = ph.GetPageID(pageID);
        if(rc!=OK) return rc;

        if(headerPage.bitmap.test(pageID) == false) {
            //if(headerPage.bitmap[pageID] == false)
            break;
        }
        else {
            rc = fh.UnpinPage(pageID);
            if(rc!=OK) return rc;
        }
    }
    //βρήκαμε σε ποια σελίδα θα μπεί η εγγραφή.
    if(i==numReservedPages) //πρέπει να κάνουμε νέο page reserve.
    {
        if(i == 101) return REM_PAGES_ARE_FULL;
        rc = fh.ReservePage(ph);
        if(rc!=OK) return rc;
        rc = ph.GetPageID(pageID);
        if(rc!=OK) return rc;
        rc = ph.GetDataPtr(&pageData);
        if(rc!=OK) return rc;
        //κάνουμε αρχικοποίηση το record header
        rh.recordHeader.reservedRecords=0;
        for(int i=0; i<headerPage.recordsPerPage; i++)
            //rh.recordHeader.bitmap[i] = false;
            rh.recordHeader.bitmap.set(i,0);

    }
    else { //δεν κάνουμε reserve νεo page, υπάρχει ήδη, διαβάζουμε το record header.

        rc = fh.GetPage(pageID,ph);
        if(rc!=OK) return rc;
        rc = ph.GetDataPtr(&pageData);
        if(rc!=OK) return rc;
        memcpy(&rh.recordHeader, pageData, sizeof(REM_RecordHandle::RecordHeader));

    }

    //mexri tora vrikame pageID. Πάμε να βρούμε το slot όπου θα μπούν τα δεδομένα.
    int slot = -1;
    for(i=0; i<headerPage.recordsPerPage; i++) {
        //10: bitmap size
        //if(rh.recordHeader.bitmap[i] == false)
        if(rh.recordHeader.bitmap.test(i) == false)
        {
            slot = i;
            break;
        }
    }

    //βρήκαμε page και slot όπου θα βάλουμε τα δεδομένα.

    //ενημέρωση του record handle για την εγγραφή όπου θα μπούν τα δεδομένα.
    rh.Initialize(ph, slot, this->headerPage.recordSize);
    //εγγραφή των δεδομένων στο record.
    UpdateRecord(rh);
    //ενημέρωση του recordHeader
    rh.recordHeader.reservedRecords++;
    rh.recordHeader.bitmap.set(slot,1);
    //rh.recordHeader.bitmap[slot] = true;
    //εγγραφή του recordHeader στη σελίδα.
    memcpy(pageData, &rh.recordHeader,sizeof(REM_RecordHandle::RecordHeader));
    //ενημέρωση της σελίδας με τις αλλαγές.
    rc = fh.MarkPageDirty(pageID);
    if(rc!=OK) return rc;
    rc = fh.UnpinPage(pageID);
    if(rc!=OK) return rc;
    //ενημέρωση του page header εάν χρειάζεται
    if(rh.recordHeader.reservedRecords == headerPage.recordsPerPage) { //είναι full η σελίδα..
        rc = updatePageHeader(pageID, true);
        if(rc!=OK) return rc;
    }
    //ενημέρωση του record id

    rid.SetPageID(pageID);
    rid.SetSlot(slot);
    return OK;
}
t_rc REM_RecordFileHandle::InsertRecord(const char *pData, REM_RecordID &rid)	{
    /* Check is file is open. */
    if (!this->isOpen) {
        return REM_FHCLOSED;
    }
    t_rc rc;

    /* Find an empty page to write the new record. */
    STORM_PageHandle targetPage;
    REM_PageHeader pageHeader = {0}; // The default number of records in a page is 0.
    char *pageData;

    /*	If there is no free space (lastPageID=-1) then we reserve a new page. */
    if (this->remFileHeader.isLastPageFull) {

        rc = sfh.ReservePage(targetPage);	// Reserve the new page.
        if (rc != OK) {
            return rc;
        }

        /* We mark the last page as not full. */
        this->remFileHeader.isLastPageFull = false;

        /* We update the file header and mark as dirty. */
        memcpy(this->pData_FileHeader, &this->remFileHeader, REM_FILEHEADER_SIZE);

        rc = this->sfh.MarkPageDirty(this->pageNum_FileHeader);
        if (rc != OK) {
            return rc;
        }

        /* Get a pointer to the data of the new page to write the new data. */
        rc = targetPage.GetDataPtr(&pageData);
        if (rc != OK) {
            return rc;
        }

    }
    /* If we have free space in a page, we just get the page. */
    else {
        rc = this->sfh.GetLastPage(targetPage);
        if (rc != OK) {
            return rc;
        }

        /* Get a pointer to the data of the the page to read the REM Page Header. */
        rc = targetPage.GetDataPtr(&pageData);
        if (rc != OK) {
            return rc;
        }

        memcpy(&pageHeader, pageData, REM_PAGEHEADER_SIZE);

    }

    /* We write the data to the proper position. The new record offset must be the page header size + the offset of each record there
     * is inside the page. We always place the new record at the end of the page.
     */
    memcpy(&pageData[REM_PAGEHEADER_SIZE+(pageHeader.nRecords*this->remFileHeader.recordSize)], pData, this->remFileHeader.recordSize);

    /* Increase the number of records in the page header. This number is also the slot number of the record. */
    int slotNum = ++pageHeader.nRecords;
    /* Declare page number, which is the pageID we are currently working on. */
    int pageNum;
    rc = targetPage.GetPageID(pageNum);
    if (rc != OK) {
        return rc;
    }

    /* Check if page is full. */
    if (pageHeader.nRecords == this->remFileHeader.recordsPerPage) {
        this->remFileHeader.isLastPageFull = true;

        /* We update the file header and mark as dirty. */
        memcpy(this->pData_FileHeader, &this->remFileHeader, REM_FILEHEADER_SIZE);

        rc = this->sfh.MarkPageDirty(this->pageNum_FileHeader);
        if (rc != OK) {
            return rc;
        }

        /* Get a pointer to the data of the new page to write the new data. */
        rc = targetPage.GetDataPtr(&pageData);
        if (rc != OK) {
            return rc;
        }
    }

    /* Write the new REM Page Header. */
    memcpy(pageData, &pageHeader, REM_PAGEHEADER_SIZE);


    /* Mark the page as dirty because we modified it */
    rc = this->sfh.MarkPageDirty(pageNum);
    if (rc != OK) {
        return rc;
    }

    this->sfh.FlushPage(pageNum);	// We should reconsider when we are flushing pages!!!

    /* Unpin the page */
    rc = this->sfh.UnpinPage (pageNum);
    if (rc != OK) {
        return rc;
    }

    /* Set the passed RID's page number and slot number */
    rc = rid.SetPageID(pageNum);
    if (rc != OK) {
        return rc;
    }
    rc = rid.SetSlot(slotNum);
    if (rc != OK) {
        return rc;
    }

    /* Successfuly inserted record */
    return (OK);
}