package net.sowgro.npehero.levelapi; import java.io.*; import com.google.gson.Gson; import com.google.gson.GsonBuilder; import javafx.scene.image.Image; import javafx.scene.media.Media; import javafx.scene.media.MediaPlayer; import javafx.scene.paint.Color; import java.nio.file.Files; import java.nio.file.StandardCopyOption; import java.util.Map; public class Level implements Comparable{ public static final String SONG_FILE = "song"; public static final String BACKGROUND_FILE = "background"; public static final String PREVIEW_FILE = "preview"; public final File dir; public String title = "Unnamed"; public String artist = "Unknown"; public String desc; public Color[] colors = {Color.RED,Color.BLUE,Color.GREEN,Color.PURPLE,Color.YELLOW}; public Image preview; public Image background; public Media song; public Difficulties difficulties; private final File jsonFile; private final Gson jsonParser = new GsonBuilder().serializeNulls().setPrettyPrinting().create(); private File songFile; private File previewFile; private File backgroundFile; /** * Creates a new level * @param newDir The path of the Level * @throws IOException If there is a problem reading the metadata file or loading the difficulties */ public Level(File newDir) throws IOException { dir = newDir; jsonFile = new File(dir, "metadata.json"); readFiles(); readMetadata(); difficulties = new Difficulties(this); } /** * Check for a song file, background file and preview image file */ public void readFiles() { songFile = null; previewFile = null; backgroundFile = null; song = null; background = null; preview = null; File[] fileList = dir.listFiles(); if (fileList == null) { return; } for (File file : fileList) { String fileName = file.getName(); if (fileName.contains(SONG_FILE)) { songFile = file; song = new Media(file.toURI().toString()); new MediaPlayer(song); // allows song.getDuration() to return } else if (fileName.contains(BACKGROUND_FILE)) { backgroundFile = file; background = new Image(file.toURI().toString()); } else if (fileName.contains(PREVIEW_FILE)) { previewFile = file; preview = new Image(file.toURI().toString()); } } } /** * Read in metadata file * @throws IOException If there is a problem reading the file */ public void readMetadata() throws IOException { if (!jsonFile.exists()) { return; } @SuppressWarnings("unchecked") Map data = jsonParser.fromJson(new FileReader(jsonFile), Map.class); title = (String) data.getOrDefault("title", title); artist = (String) data.getOrDefault("artist", artist); desc = (String) data.getOrDefault("desc", desc); colors[0] = Color.web((String) data.getOrDefault("color1", colors[0].toString())); colors[1] = Color.web((String) data.getOrDefault("color2", colors[1].toString())); colors[2] = Color.web((String) data.getOrDefault("color3", colors[2].toString())); colors[3] = Color.web((String) data.getOrDefault("color4", colors[3].toString())); colors[4] = Color.web((String) data.getOrDefault("color5", colors[4].toString())); } /** * Checks if the level is valid. *

* A valid level has a song file and 1 or more valid difficulties * @return True if the level is valid */ public boolean isValid() { if (song == null) { return false; } if (difficulties.getValidList().isEmpty()) { return false; } return true; } /** * Writes metadata to json file * @throws IOException If there is a problem writing to the file. */ public void writeMetadata() throws IOException { if (!jsonFile.exists() && !jsonFile.createNewFile()) { throw new IOException("Could not create file " + jsonFile.getAbsolutePath()); } @SuppressWarnings("unchecked") Map data = jsonParser.fromJson(new FileReader(jsonFile), Map.class); data.put("title", title); data.put("artist", artist); data.put("desc", desc); data.put("color1",colors[0].toString()); data.put("color2",colors[1].toString()); data.put("color3",colors[2].toString()); data.put("color4",colors[3].toString()); data.put("color5",colors[4].toString()); FileWriter fileWriter = new FileWriter(jsonFile); jsonParser.toJson(data, fileWriter); fileWriter.close(); } /** * Copies a file into the level directory with the name provided. The extension will be inherited from the source file * @param source: the file to be copied * @param name: the new file name EXCLUDING the extension. * @throws IOException If there is a problem adding the file */ public void addFile(File source, String name) throws IOException { name = name + "." + getFileExtension(source); Files.copy(source.toPath(), new File(dir, name).toPath(), StandardCopyOption.REPLACE_EXISTING); readFiles(); } /** * Deletes a file from the level's directory * @param name the new file name EXCLUDING the extension. * @throws IOException If there is a problem deleting the file */ public void removeFile(String name) throws IOException { File f = switch (name) { case SONG_FILE -> songFile; case BACKGROUND_FILE -> backgroundFile; case PREVIEW_FILE -> previewFile; default -> throw new IllegalArgumentException("Invalid file name " + name); }; if (!f.delete()) { throw new IOException("Failed to delete file " + f.getAbsolutePath()); } readFiles(); } @Override public int compareTo(Level other) { return title.compareTo(other.title); } /** * Get the extension of a file. * @param file The file to return the extension of * @return The extension of the file in the format "*.ext" */ public String getFileExtension(File file) { return file.getName().substring(file.getName().lastIndexOf('.') + 1); } }