/**
   * Create an index file for the specified column.
   *
   * @param colname the column's name
   * @return the time it took to run this method.
   * @throws Exception
   */
  public long createIndexFile() throws Exception {
    long s = System.currentTimeMillis();
    // fill idx file with hashsize empty records/lines (empty means filled with spaces)

    int pkindex = def.getColPosition(def.getPK());
    if (pkindex == -1) {
      throw new Exception("Primary key does not exist");
    }
    Integer[] size = def.getSizes();
    int recordSize = idxFixedRecordLength() + size[pkindex];

    StringBuffer temp = new StringBuffer();
    for (int i = 0; i < recordSize - 2; i++) {
      temp.append(" ");
    }

    indexFile.seek(0);
    for (int i = 0; i < this.hashsize; i++) {
      indexFile.writeBytes(temp + "\r\n");
    }

    int table_pos = 0;
    // create an index entry for each row present in the tbl-file (for column=colname)
    String line = null;
    tableFile.seek(0);
    while ((line = tableFile.readLine()) != null) {
      // get column value (don't strip the spaces)
      String pkvalue = line.split("#")[pkindex];
      addIndexEntry(table_pos, pkvalue);
      table_pos++;
    }
    long e = System.currentTimeMillis();
    return e - s;
  }
  /**
   * Create an index entry in the idx file of the specified column.
   *
   * @param tablePosition position or line nr in table *.tbl
   * @param pkValue the value of the primary key to create an index entry for
   * @throws Exception
   */
  protected void addIndexEntry(int tablePosition, String pkValue) throws Exception {
    if (!indexExists(def.getPK())) {
      throw new Exception("No index created");
    }
    int pkindex = def.getColPosition(def.getPK());
    if (pkindex == -1) {
      throw new Exception("Primary key does not exist");
    }
    Integer[] size = def.getSizes();
    if (pkValue.length() > TableDefinition.INTEGER_SIZE) {
      throw new Exception("Supplied pkValue too large");
    } else {
      // make sure key value has appropriate length
      StringBuffer temp = new StringBuffer();
      temp.append(pkValue);
      for (int i = 0; i < TableDefinition.INTEGER_SIZE - pkValue.length(); i++) {
        temp.append(' ');
      }
      pkValue = temp.toString();
    }

    // calculate index = hash value
    String s_value = pkValue.trim();
    int indexPosition = hash(s_value);
    int recordSize = idxFixedRecordLength() + size[pkindex];

    indexFile.seek(indexPosition * recordSize);
    String line = indexFile.readLine();

    if (line.substring(0, 1).equals(" ")) {
      // empty record, reset file pointer and fill record
      indexFile.seek(indexPosition * recordSize);

      String indexPositionFormatted = String.format("%-5s", Integer.toString(indexPosition));
      String tablePositionFormatted = String.format("%-5s", Integer.toString(tablePosition));

      String indexRecord =
          indexPositionFormatted
              + "# #"
              + pkValue
              + "#"
              + tablePositionFormatted
              + "#"
              + "null "
              + "\r\n";

      indexFile.writeBytes(indexRecord);
    } else {
      String[] parts = line.split("#");
      if (parts[1].equals("D")) {
        // Deleted record, reset file pointer, fill record but keep previous link !
        indexFile.seek(indexPosition * recordSize);

        String indexPositionFormatted = String.format("%-5s", Integer.toString(indexPosition));
        String tablePositionFormatted = String.format("%-5s", Integer.toString(tablePosition));

        String indexRecord =
            indexPositionFormatted + "# #" + pkValue + "#" + tablePositionFormatted;

        indexFile.writeBytes(indexRecord);
      } else {
        // Collision found ! a valid record is found, so add new record at EOF
        // Calculate new record number
        int newIndexPosition = (int) (indexFile.length() / recordSize);

        String newIndexPositionFormatted =
            String.format("%-5s", Integer.toString(newIndexPosition));
        String tablePositionFormatted = String.format("%-5s", Integer.toString(tablePosition));

        // reset file pointer and update the current record
        indexFile.seek((indexPosition * recordSize) + (recordSize - 2 - 5));
        indexFile.write(newIndexPositionFormatted.toString().getBytes());

        // move file pointer to EOF and append new record
        indexFile.seek(indexFile.length());
        String indexRecord =
            newIndexPositionFormatted
                + "# #"
                + pkValue
                + "#"
                + tablePositionFormatted
                + "#"
                + "null "
                + "\r\n";

        indexFile.writeBytes(indexRecord);
      }
    }
  }