package magic.ui.theme;
import magic.ui.MagicImages;
import javax.swing.ImageIcon;
import java.awt.Color;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Path;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import magic.ui.ImageFileIO;
import static magic.ui.theme.Theme.ICON_SMALL_BATTLEFIELD;
import static magic.ui.theme.Theme.ICON_SMALL_COMBAT;
import magic.utility.FileIO;
import magic.utility.MagicFileSystem;
public class CustomTheme extends AbstractTheme {
private static final String THEME_PROPERTIES_FILE="theme.properties";
private static final int MAX_AVATARS=100;
private final File file;
private ZipFile zipFile;
private final PlayerAvatar[] playerAvatars;
private int nrOfAvatars;
private final Map<String, BufferedImage> imagesMap;
public CustomTheme(final File file) {
super(getThemeName(file));
addToTheme(ICON_SMALL_BATTLEFIELD, null);
addToTheme(ICON_SMALL_COMBAT, null);
this.file = file;
playerAvatars = new PlayerAvatar[MAX_AVATARS];
imagesMap = new HashMap<>();
}
public static String getThemeName(final File aFile) {
final String name = aFile.getName();
if (aFile.isFile()) {
if (name.endsWith("_theme.zip")) {
return name.substring(0, name.length() - "_theme.zip".length());
}
if (name.endsWith(".zip")) {
return name.substring(0, name.length() - ".zip".length());
}
}
if (name.endsWith("_theme")) {
return name.substring(0, name.length() - "_theme".length());
}
return name;
}
@Override
public ImageIcon getAvatarIcon(final int index,final int size) {
if (nrOfAvatars==0) {
return super.getAvatarIcon(index, size);
}
return playerAvatars[index%nrOfAvatars].getIcon(size);
}
private void parseEntry(final String key,final String value) {
if (value.isEmpty()) {
return;
}
final int index=key.indexOf('_');
if (index<0) {
return;
}
Object typeValue=null;
final String type=key.substring(0,index);
if ("avatar".equals(type)) {
final int avatarIndex=Integer.parseInt(key.substring(index+1));
if (avatarIndex>0&&avatarIndex<=MAX_AVATARS) {
final BufferedImage image=loadImage("avatars/"+value);
playerAvatars[avatarIndex-1]=new PlayerAvatar(image);
nrOfAvatars=Math.max(avatarIndex,nrOfAvatars);
}
return;
}
if ("value".equals(type)) {
typeValue=Integer.parseInt(value);
} else if ("color".equals(type)) {
final String[] parts=value.split(",");
final int r=Integer.parseInt(parts[0],16);
final int g=Integer.parseInt(parts[1],16);
final int b=Integer.parseInt(parts[2],16);
if (parts.length==4) {
typeValue=new Color(r,g,b,Integer.parseInt(parts[3],16));
} else if (parts.length==3) {
typeValue=new Color(r,g,b);
}
} else if ("texture".equals(type)) {
typeValue=value;
} else if ("icon".equals(type)) {
typeValue = value.isEmpty() ? null : new ImageIcon(loadImage(value));
} else if ("option".equals(type)) {
typeValue = Boolean.parseBoolean(value);
}
// add or replace existing/default value.
if (typeValue != null) {
addToTheme(key, typeValue);
}
}
private InputStream getInputStream(final String filename) {
try { //get input stream
if (zipFile!=null) {
final ZipEntry zipEntry=zipFile.getEntry(filename);
return zipFile.getInputStream(zipEntry);
} else {
return new FileInputStream(new File(file,filename));
}
} catch (final IOException ex) {
System.err.println("ERROR! Unable to obtain input stream from " + filename);
return null;
}
}
private BufferedImage loadImage(final String filename) {
final InputStream ins = getInputStream(filename);
return ImageFileIO.toImg(ins, MagicImages.MISSING_BIG);
}
@Override
public void load() {
if (file.isFile()) {
try { //create zip file
zipFile=new ZipFile(file);
} catch (final java.util.zip.ZipException ex) {
System.err.println("ERROR! Unable to create ZipFile from " + file);
} catch (final IOException ex) {
System.err.println("ERROR! Unable to create ZipFile from " + file);
}
}
final InputStream inputStream=getInputStream(THEME_PROPERTIES_FILE);
final Properties properties=FileIO.toProp(inputStream);
for (final Map.Entry<Object,Object> entry : properties.entrySet()) {
parseEntry(entry.getKey().toString(),entry.getValue().toString().trim());
}
}
static File getThemeFile(String name) {
final Path path = MagicFileSystem.getThemesPath();
if (path.resolve(name).toFile().exists()) {
return path.resolve(name).toFile();
}
if (path.resolve(name + "_theme").toFile().exists()) {
return path.resolve(name + "_theme").toFile();
}
if (path.resolve(name + ".zip").toFile().exists()) {
return path.resolve(name + ".zip").toFile();
}
if (path.resolve(name + "_theme.zip").toFile().exists()) {
return path.resolve(name + "_theme.zip").toFile();
}
return null;
}
static Theme loadTheme(String name) {
if (getThemeFile(name) != null) {
final Theme t = new CustomTheme(getThemeFile(name));
t.load();
return t;
}
return null;
}
private BufferedImage getImage(String imageKey, String filename) {
if (!imagesMap.containsKey(imageKey)) {
imagesMap.put(imageKey, loadImage(filename));
}
return imagesMap.get(imageKey);
}
@Override
public BufferedImage getTexture(String name) {
return hasValue(name)
? getImage(name, getStringValue(name))
: MagicImages.MISSING_BIG;
}
}