001package fr.aumgn.dac2.arena;
002
003import java.io.File;
004import java.util.ArrayList;
005import java.util.Collections;
006import java.util.HashMap;
007import java.util.List;
008import java.util.Map;
009
010import org.bukkit.World;
011import org.bukkit.entity.Player;
012
013import fr.aumgn.bukkitutils.geom.Vector;
014import fr.aumgn.bukkitutils.gson.GsonLoadException;
015import fr.aumgn.bukkitutils.gson.GsonLoader;
016import fr.aumgn.dac2.DAC;
017import fr.aumgn.dac2.DACPlugin;
018import fr.aumgn.dac2.arena.regions.StartRegion;
019import fr.aumgn.dac2.exceptions.ArenaDeleteException;
020import fr.aumgn.dac2.exceptions.ArenaSaveException;
021import fr.aumgn.dac2.exceptions.ArenasFolderException;
022
023public class Arenas {
024
025    private static final String DIRECTORY = "arenas";
026
027    private Map<String, Arena> arenas;
028
029    public Arenas(DAC dac) {
030        load(dac);
031    }
032
033    private File getFolder(DACPlugin plugin) {
034        File folder = new File(plugin.getDataFolder(), DIRECTORY);
035
036        if (folder.exists()) {
037            if (!folder.isDirectory()) {
038                throw new ArenasFolderException(
039                        folder.getPath() + " is not a directory.");
040            }
041        } else if (!folder.mkdirs()) {
042            throw new ArenasFolderException(
043                    "Unable to create " + folder.getPath() + " directory.");
044        }
045
046        return folder;
047    }
048
049    private String filenameFor(DAC dac, Arena arena) {
050        return getFolder(dac.getPlugin()).getName() + File.separator
051                + arena.getName() + ".json";
052    }
053
054    private String arenaNameFor(File file) {
055        String name = file.getName();
056        int index = name.lastIndexOf(".");
057        return name.substring(0, index);
058    }
059
060    public void load(DAC dac) {
061        arenas = new HashMap<String, Arena>();
062
063        GsonLoader loader = dac.getPlugin().getGsonLoader();
064        File folder = getFolder(dac.getPlugin());
065        for (File file : folder.listFiles()) {
066            try {
067                Arena arena = loader.load(file, Arena.class);
068                String nameFromFile = arenaNameFor(file);
069                if (!nameFromFile.equals(arena.getName())) {
070                    dac.getLogger().severe("Filename `" + nameFromFile
071                            + "` does not match arena's name `"
072                            + arena.getName() + "`. Skipping it.");
073                    continue;
074                }
075                arenas.put(arena.getName(), arena);
076            } catch (GsonLoadException exc) {
077                dac.getLogger().severe(
078                        "Unable to read " + file.getName() + " arena's file.");
079            }
080        }
081    }
082
083    public void saveArena(DAC dac, Arena arena) {
084        saveArena(dac, dac.getPlugin().getGsonLoader(), arena);
085    }
086
087    private void saveArena(DAC dac, GsonLoader loader, Arena arena) {
088        String filename = filenameFor(dac, arena);
089        try {
090            loader.write(filename, arena);
091        } catch (GsonLoadException _) {
092            throw new ArenaSaveException("Unable to save " + filename + ".");
093        }
094    }
095
096    public void saveAll(DAC dac) {
097        for (Arena arena : arenas.values()) {
098            saveArena(dac, dac.getPlugin().getGsonLoader(), arena);
099        }
100    }
101
102    public boolean has(String name) {
103        return arenas.containsKey(name);
104    }
105
106    public Arena get(String name) {
107        return arenas.get(name);
108    }
109
110    /**
111     * Gets the arena in whose start region the player is in.
112     *
113     * If different arena defines start regions which overlap themselves,
114     * the result is undefined.
115     *
116     * @param player
117     * @return the arena
118     */
119    public Arena get(Player player) {
120        Vector pt = new Vector(player);
121        for (Arena arena : arenas.values()) {
122            StartRegion startRegion = arena.getStartRegion();
123            if (startRegion != null && startRegion.contains(pt)) {
124                return arena;
125            }
126        }
127
128        return null;
129    }
130
131    public void create(DAC dac, String name, World world) {
132        Arena arena = new Arena(name, world);
133        arenas.put(name, arena);
134        saveArena(dac, arena);
135    }
136
137    public void delete(DAC dac, Arena arena) {
138        arenas.remove(arena.getName());
139        String filename  = filenameFor(dac, arena);
140        File file = new File(dac.getPlugin().getDataFolder(), filename);
141        if (!file.delete()) {
142            throw new ArenaDeleteException("Unable to delete " + filename
143                    + " arena's file.");
144        }
145    }
146
147    public List<Arena> all() {
148        return Collections.unmodifiableList(new ArrayList<Arena>(
149                arenas.values()));
150    }
151
152    public int length() {
153        return arenas.values().size();
154    }
155}