package model;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.nio.charset.StandardCharsets;

/**
 * The Level class.
 *
 * @author Eli Skeggs
 */
public class Level {
  // TODO: where should these be stored?
  public static String header = "SWLV";
  public static int version = 0;

  public Rules rules;
  public Board initialBoard;

  // TODO: these really feel like they belong elsewhere...
  public Board currentBoard;
  public int currentScore;

  /**
   * Create a Level with reasonable default settings.
   */
  public Level() {
    rules = new Rules();
    initialBoard = new Board(rules);
    currentBoard = null;
    currentScore = 0;
  }

  /**
   * Clones a Level from the given Level.
   *
   * @param src
   */
  public Level(Level src) {
    rules = new Rules(src.rules);
    initialBoard = new Board(src.initialBoard);
    currentBoard = null;
    currentScore = 0;
  }

  /**
   * Creates a Level from a DataInputStream.
   *
   * @param in
   */
  public Level(DataInputStream in) throws IOException {
    byte headerBytes[] = new byte[4];
    if (in.read(headerBytes, 0, 4) != 4) {
      throw new RuntimeException("stored level incomplete");
    }
    if (!header.equals(new String(headerBytes, StandardCharsets.US_ASCII))) {
      throw new RuntimeException("provided data stream is not a stored level");
    }

    // not a stellar system, but good enough given that we'll likely only have
    // one or two versions in use
    int version = in.readInt();
    if (version != Level.version) {
      throw new RuntimeException("provided data stream has incompatible version");
    }

    rules = new Rules(in);
    initialBoard = new Board(rules, in);
    currentBoard = null;
    currentScore = 0;
  }

  /**
   * Write the Level to a DataOutputStream.
   *
   * @param out
   */
  public void write(DataOutputStream out) throws IOException {
    out.write(header.getBytes(StandardCharsets.US_ASCII));
    out.writeInt(version);
    rules.write(out);
    initialBoard.write(out);
  }

  /**
   * Realize the Board - fill in the unknown Tiles.
   *
   * Call this when we want to play a game as a player.
   */
  public void realizeBoard() {
    currentBoard = new Board(initialBoard);
    currentBoard.realizeTiles();
    currentScore = 0;
  }

  /**
   * Discards the realization of the Board, if applicable.
   *
   * Call this when we're done playing a game as a player.
   */
  public void discardBoard() {
    currentBoard = null;
    currentScore = 0;
  }
}

@@ -89,27 +89,108 @@
 java.io.
-IOException
+File;%0Aimport java.io.FileInputStream;%0Aimport java.io.IOException;%0Aimport java.io.InputStream
 ;%0Aimport
@@ -583,16 +583,865 @@
 Score;%0A%0A
+  /**%0A   * Checks the header of the given InputStream to ensure it is a level.%0A   *%0A   * @param in The stream to check.%0A   * @return Whether the given file could be a valid level.%0A   */%0A  protected static boolean checkHeader(InputStream in) throws IOException %7B%0A    byte headerBytes%5B%5D = new byte%5B4%5D;%0A    if (in.read(headerBytes) != headerBytes.length) %7B%0A      return false;%0A    %7D%0A%0A    if (!header.equals(new String(headerBytes, StandardCharsets.US_ASCII))) %7B%0A      return false;%0A    %7D%0A%0A    return true;%0A  %7D%0A%0A  /**%0A   * Checks the header of the given file to ensure it is a level.%0A   *%0A   * @param file%0A   * @return Whether the given file could be a valid level.%0A   */%0A  public static boolean checkHeader(File file) %7B%0A    try %7B%0A      return Level.checkHeader(new FileInputStream(file));%0A    %7D catch (IOException err) %7B%0A      return false;%0A    %7D%0A  %7D%0A%0A
   /**%0A  
@@ -2009,225 +2009,33 @@
     
-byte headerBytes%5B%5D = new byte%5B4%5D;%0A    if (in.read(headerBytes, 0, 4) != 4) %7B%0A      throw new RuntimeException(%22stored level incomplete%22);%0A    %7D%0A    if (!header.equals(new String(headerBytes, StandardCharsets.US_ASCII)
+if (!Level.checkHeader(in
 )) %7B

Implement quick Level file header verification