package it.albertus.cycles.model;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.zip.CRC32;
import java.util.zip.Checksum;
import it.albertus.cycles.data.DefaultBikes;
import it.albertus.cycles.model.Bike.BikeType;
import it.albertus.cycles.resources.Messages;
import it.albertus.util.ByteUtils;
import it.albertus.util.IOUtils;
public class BikesInf {
public static final String FILE_NAME = "BIKES.INF";
public static final short FILE_SIZE = 444;
private final Bike[] bikes = new Bike[3];
public BikesInf(final InputStream bikesInfInputStream) throws IOException {
read(bikesInfInputStream);
}
public BikesInf(final File file) throws IOException {
FileInputStream fis = null;
BufferedInputStream bis = null;
try {
fis = new FileInputStream(file);
bis = new BufferedInputStream(fis);
read(bis);
}
finally {
IOUtils.closeQuietly(bis, fis);
}
}
public void reset(final BikeType type) throws IOException {
InputStream is = null;
try {
is = new DefaultBikes().getInputStream();
read(is, type);
}
finally {
IOUtils.closeQuietly(is);
}
}
private void read(final InputStream inf, BikeType... types) throws IOException {
final byte[] inf125 = new byte[Bike.LENGTH];
final byte[] inf250 = new byte[Bike.LENGTH];
final byte[] inf500 = new byte[Bike.LENGTH];
final boolean wrongFileSize = inf.read(inf125) != Bike.LENGTH || inf.read(inf250) != Bike.LENGTH || inf.read(inf500) != Bike.LENGTH || inf.read() != -1;
inf.close();
if (wrongFileSize) {
throw new IllegalStateException(Messages.get("err.wrong.file.size"));
}
System.out.println(Messages.get("msg.file.read", FILE_NAME));
if (types == null || types.length == 0) {
/* Full reading */
bikes[0] = new Bike(BikeType.CLASS_125, inf125);
bikes[1] = new Bike(BikeType.CLASS_250, inf250);
bikes[2] = new Bike(BikeType.CLASS_500, inf500);
}
else {
/* Replace only selected bikes */
final byte[][] infs = new byte[3][];
infs[0] = inf125;
infs[1] = inf250;
infs[2] = inf500;
for (final BikeType type : types) {
bikes[type.ordinal()] = new Bike(type, infs[type.ordinal()]);
}
}
System.out.println(Messages.get("msg.file.parsed", FILE_NAME));
}
public void write(final String fileName) throws IOException {
final byte[] newBikesInf = this.toByteArray();
final Checksum crc = new CRC32();
crc.update(newBikesInf, 0, newBikesInf.length);
System.out.println(Messages.get("msg.configuration.changed", crc.getValue() == DefaultBikes.CRC ? ' ' + Messages.get("msg.not") + ' ' : ' ', String.format("%08X", crc.getValue())));
FileOutputStream fos = null;
BufferedOutputStream bos = null;
try {
fos = new FileOutputStream(fileName);
bos = new BufferedOutputStream(fos, FILE_SIZE);
bos.write(newBikesInf);
}
finally {
IOUtils.closeQuietly(bos, fos);
}
System.out.println(Messages.get("msg.new.file.written.into.path", FILE_NAME, "".equals(fileName) ? '.' : fileName, String.format("%08X", crc.getValue())));
}
/**
* Ricostruisce il file BIKES.INF a partire dalle 3 configurazioni contenute
* nell'oggetto (125, 250, 500).
*
* @return L'array di byte corrispondente al file BIKES.INF.
*/
private byte[] toByteArray() {
final List<Byte> byteList = new ArrayList<Byte>(FILE_SIZE);
for (final Bike bike : bikes) {
byteList.addAll(bike.toByteList());
}
if (byteList.size() != FILE_SIZE) {
throw new IllegalStateException(Messages.get("err.wrong.file.size.detailed", FILE_NAME, FILE_SIZE, byteList.size()));
}
return ByteUtils.toByteArray(byteList);
}
public Bike getBike(int displacement) {
for (final Bike bike : bikes) {
if (bike.getType().getDisplacement() == displacement) {
return bike;
}
}
return null;
}
public Bike[] getBikes() {
return bikes;
}
}