/* PokemonBox.java
*
* Created on Wednesday June 2, 2010, 1:44 PM
*
* This file is a part of Shoddy Battle.
* Copyright (C) 2009 Catherine Fitzpatrick and Benjamin Gwin
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Affero General Public License
* as published by the Free Software Foundation; either version 3
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program; if not, visit the Free Software Foundation, Inc.
* online at http://gnu.org.
*/
package shoddybattleclient.shoddybattle;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.Writer;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import shoddybattleclient.Preference;
import shoddybattleclient.utils.TeamFileParser;
/**
* Pokemon boxes are used both by BoxTreeModel and BoxDialog, so this class
* exists to avoid code repetition.
* @author Carlos
*/
public class PokemonBox implements Comparable<PokemonBox> {
public class PokemonWrapper implements Comparable<PokemonWrapper> {
public String name;
public Pokemon pokemon;
public PokemonWrapper(String pokemonName, Pokemon poke) {
name = pokemonName;
pokemon = poke;
}
public PokemonBox getParent() {
return PokemonBox.this;
}
@Override
public String toString() {
return name;
}
@Override
public int compareTo(PokemonWrapper o) {
int compare = name.compareToIgnoreCase(o.name);
if (compare == 0)
compare = getParent().compareTo(o.getParent());
return compare;
}
@Override
public boolean equals(Object o2) {
if (o2 == null) return false;
if (!o2.getClass().equals(getClass())) return false;
PokemonWrapper other = (PokemonWrapper)o2;
if (name.equalsIgnoreCase(other.name) &&
getParent().equals(other.getParent()))
return true;
else
return false;
}
@Override
public int hashCode() {
return name.toUpperCase().hashCode();
}
}
private String m_name;
private ArrayList<PokemonWrapper> m_pokemon;
private Generation m_generation;
public PokemonBox(String name, Generation generation) {
this(name, null, generation);
}
public PokemonBox(String name, String species, Generation generation) {
m_name = name;
m_generation = generation;
loadContents(species);
}
private void loadContents(String species) {
m_pokemon = new ArrayList<PokemonWrapper>();
//Create the box itself if it doesn't exist
File boxDir = getBoxFolder();
if (!boxDir.exists())
boxDir.mkdirs();
//Read in all the pokemon in this box
for (File pokeFile : boxDir.listFiles()) {
if (pokeFile.isDirectory()) continue;
try {
TeamFileParser tfp = new TeamFileParser();
Pokemon poke = tfp.parseTeam(
pokeFile.getAbsolutePath(), m_generation)[0];
if (species == null || poke.toString().equals(species))
m_pokemon.add(new PokemonWrapper(pokeFile.getName(), poke));
}
catch (Exception ex) {}
}
Collections.sort(m_pokemon);
clearDuplicates(m_pokemon);
}
//On *nix systems, PokemonBox allows duplicates on first load.
//This clears those duplicates from the list.
//This list MUST be sorted before using this method
private void clearDuplicates(List<PokemonWrapper> list) {
//Sorted lists allow us to do this in O(n)
Iterator<PokemonWrapper> iter = list.iterator();
Comparable<PokemonWrapper> previous = null;
while (iter.hasNext()) {
PokemonWrapper current = iter.next();
//this only happens once, but it makes the code cleaner
if (previous == null) {
previous = current;
continue;
}
if (previous.compareTo(current) == 0)
iter.remove();
previous = current;
}
}
//This creates a new file if it doesn't exist
public void addPokemon(String name, Pokemon pokemon) throws IOException {
PokemonWrapper wrapper = new PokemonWrapper(name, pokemon);
StringBuffer buf = new StringBuffer();
buf.append("<?xml version=\"1.0\" encoding=\"UTF-8\" ?>");
buf.append(wrapper.pokemon.toXML());
File pokemonPath = new File(getBoxPath() + "/" + wrapper.name);
Writer writer = new PrintWriter(new FileWriter(pokemonPath));
writer.write(new String(buf));
writer.flush();
writer.close();
//Insert the pokemon into its sorted position
int i = 0;
for (i = 0; i < getSize(); i++) {
int compare = wrapper.compareTo(m_pokemon.get(i));
if (compare < 0) {
break;
} else if (compare == 0) {
m_pokemon.set(i, wrapper);
return;
}
}
m_pokemon.add(i, wrapper);
}
public int indexOf(PokemonWrapper wrapper) {
int index = Collections.binarySearch(m_pokemon, wrapper);
if (index < 0)
return -1;
return index;
}
public int indexOf(String name) {
//Wrappers compare using names, so a dud allows us to search in O(logn)
PokemonWrapper dud = new PokemonWrapper(name, null);
return indexOf(dud);
}
public PokemonWrapper getPokemonAt(int idx) {
return m_pokemon.get(idx);
}
public PokemonWrapper getPokemon(String name) {
int index = indexOf(name);
if (index < 0)
return null;
return m_pokemon.get(index);
}
//If the pokemon doesn't exist, it does nothing
public void removePokemon(String name) {
int index = indexOf(name);
if (index >= 0)
removePokemonAt(index);
}
public void removePokemonAt(int index) {
PokemonWrapper wrapper = getPokemonAt(index);
new File(getBoxPath() + "/" + wrapper.name).delete();
m_pokemon.remove(index);
}
public int getSize() {
return m_pokemon.size();
}
public String getName() {
return m_name;
}
public String getBoxPath() {
return Preference.getBoxLocation() + File.separatorChar + getName();
}
public File getBoxFolder() {
return new File(getBoxPath());
}
@Override
public int compareTo(PokemonBox o) {
return getName().compareToIgnoreCase(o.getName());
}
@Override
public boolean equals(Object o2) {
if (o2 == null) return false;
if (!o2.getClass().equals(getClass())) return false;
return (getName().equalsIgnoreCase(((PokemonBox)o2).getName()));
}
@Override
public int hashCode() {
return getName().toUpperCase().hashCode();
}
@Override
public String toString() {
return getName();
}
}