/**
  * Writes a byte to memory given a 32-bit integer whose low bits are interpreted as a virtual
  * address - To be implemented for all version.
  *
  * @param fourByteInteger A 32-bit integer
  * @param value The byte Value written to memory at the relevant address
  * @throws MemoryException If there is an invalid access
  */
 public void writeByte(Integer fourByteInteger, byte value) throws MemoryException {
   // TO IMPLEMENT: V0, V1, V2, V3, V4
   int pageNumber = fourByteInteger / this.pageSize;
   byte[] values = disk.readPage(pageNumber);
   byte readValue; // The value to be return
   int address; // The address to be use
   int getFrame;
   if (this.pageTable[pageNumber] == -1) { // if the page is not in memory
     if (frameTable.size() == this.numOfFrames) { // If frame table is full
       System.out.println("Evicting page " + frameTable.peek());
       this.nextFrame = this.pageTable[frameTable.peek()];
       getFrame = this.pageTable[frameTable.peek()];
       address = this.pageSize * getFrame;
       byte[] values2 = new byte[this.pageSize];
       for (int j = 0; j < this.pageSize; j++) { // Putting the evicted page contents back to disk
         values2[j] = memory.readByte(address);
         address++;
         this.byteCount++;
       }
       disk.writePage(frameTable.peek(), values2);
       this.pageTable[frameTable.peek()] = -1;
       this.frameTable.remove();
     }
     System.out.println("Bringing page " + pageNumber + " into frame " + this.nextFrame);
     this.pageTable[pageNumber] = this.nextFrame; // Adding the frame in the page table
     frameTable.addLast(pageNumber);
     address = this.nextFrame * this.pageSize; // getting the physical adress
     for (int i = 0; i < this.pageSize; i++) {
       memory.writeByte(address, values[i]);
       address++;
       this.byteCount++;
     }
     address =
         (this.pageSize * this.nextFrame)
             + (fourByteInteger
                 - (pageNumber * this.pageSize)); // translating the address to physical
     System.out.println(
         "RAM: " + this.btb.getBitString(address, bitCounter - 1) + " <-- " + value);
     memory.writeByte(address, value);
     this.nextFrame++;
     this.pageFault++;
   } else { // else the page is in memory
     System.out.println("Page " + pageNumber + " is in memory");
     getFrame = this.pageTable[pageNumber];
     address =
         (this.pageSize * getFrame)
             + (fourByteInteger
                 - (pageNumber * this.pageSize)); // translating the address to physical
     System.out.println(
         "RAM: " + this.btb.getBitString(address, bitCounter - 1) + " <-- " + value);
     memory.writeByte(address, value);
   }
 }
  /**
   * Prints the content of the disk as a sequence of lines with the format "PAGE pageNumber:
   * byteValue, byteValue, ... byteValue" to System.out, where pageNumber is a virtual page number
   * and the list of byte values corresponds to all bytes in a given page on disk - To be
   * implemented in versions V1 and above.
   *
   * @throws MemoryException If there is an invalid access
   */
  public void printDiskContent() throws MemoryException {
    // TO IMPLEMENT: V1, V2, V3, V4
    byte[] values;
    for (int i = 0; i < numOfPages; i++) {
      values = disk.readPage(i);
      System.out.print("PAGE " + i + ": ");
      for (int j = 0; j < values.length; j++) {
        if (j + 1 == values.length) {
          System.out.print(values[j]);
        } else {
          System.out.print(values[j] + ",");
        }
      }
      System.out.println();
    }

    return;
  }