package nbtool.data.log;
import java.util.Arrays;
import com.google.protobuf.Message;
import nbtool.data.SExpr;
import nbtool.data.json.Json;
import nbtool.data.json.Json.JsonValue;
import nbtool.data.json.JsonObject;
import nbtool.data.json.JsonParser.JsonParseException;
import nbtool.images.Y16Image;
import nbtool.images.Y8Image;
import nbtool.images.YUYV8888Image;
import nbtool.util.SharedConstants;
import nbtool.util.Utility;
import nbtool.util.Utility.Pair;
public class Block {
public byte[] data = null;
public JsonObject dict = null;
public String type = "";
public String whereFrom = "";
public long imageIndex = 0;
public long createdWhen = 0;
public static Block explicit(byte[] data, JsonObject dict,
String type, String where, long index, long when) {
return new Block(data,dict,
type, where, index, when );
}
public Block(byte[] data, JsonObject dict,
String type, String where, long index, long when ) {
this.data = data == null ? new byte[0] : data;
this.dict = dict == null ? new JsonObject() : dict;
this.type = type == null ? "" : type;
this.whereFrom = where == null ? "" : where;
this.imageIndex = index;
this.createdWhen = when;
}
public static Block explicit(byte[] data,
String type) {
return new Block(data, null,
type, null, 0, 0 );
}
public Block(byte[] data,
String type) {
this(data, null, type, null, 0, 0);
}
public Block() {
this(null, null, null, null, 0, 0);
}
public static Block empty() {
return new Block();
}
public JsonObject getFullDictionary() {
JsonObject obj = dict.copy().asObject();
obj.put(SharedConstants.LOG_BLOCK_TYPE(), type);
obj.put(SharedConstants.LOG_BLOCK_WHERE_FROM(), whereFrom);
obj.put(SharedConstants.LOG_BLOCK_IMAGE_INDEX(), imageIndex);
obj.put(SharedConstants.LOG_BLOCK_WHEN_MADE(), createdWhen);
obj.put(SharedConstants.LOG_BLOCK_NUM_BYTES(), data == null ? 0 : data.length);
return obj;
}
public Log parseAsLog() {
parseTypeCheck(SharedConstants.LogType_DEFAULT());
return Log.parseFrom(data);
}
public JsonValue parseAsJson() throws JsonParseException {
parseTypeCheck(SharedConstants.JsonType_DEFAULT());
return Json.parse(new String(data));
}
public SExpr parseAsSExpr() {
parseTypeCheck(SharedConstants.SexprType_DEFAULT());
return SExpr.deserializeFrom(new String(data));
}
private Pair<Integer,Integer> imagePair() {
int width = dict.get(SharedConstants.LOG_BLOCK_IMAGE_WIDTH_PIXELS()).
asNumber().asInt();
int height = dict.get(SharedConstants.LOG_BLOCK_IMAGE_HEIGHT_PIXELS()).
asNumber().asInt();
return new Pair<Integer,Integer>(width, height);
}
public YUYV8888Image parseAsYUVImage() {
parseTypeCheck(SharedConstants.YUVImageType_DEFAULT());
Pair<Integer,Integer> pair = imagePair();
// return new YUYV8888Image(pair.a / 2, pair.b, this.data);
return new YUYV8888Image(pair.a * 2, pair.b, this.data);
}
public Y16Image parseAsY16Image() {
parseTypeCheck(SharedConstants.YUVImageType_Y16());
Pair<Integer,Integer> pair = imagePair();
return new Y16Image(pair.a, pair.b, this.data);
}
public Y8Image parseAsY8Image() {
// parseTypeCheck(SharedConstants.YUVImageType_Y8(), "whiteRet", "greenRet", "orangeRet");
parseTypeCheck(SharedConstants.YUVImageType_Y8());
Pair<Integer,Integer> pair = imagePair();
return new Y8Image(pair.a, pair.b, this.data);
}
public Message parseAsProtobufOfClass(Class<? extends Message> pclass) {
if (pclass == null) {
throw new BlockParseException(this.type, String.format("protobuf<null>") );
}
parseTypeCheck(pclass.getSimpleName());
Message parsed = Utility.protobufInstanceForClassWithData(pclass, this.data);
if (parsed == null) {
throw new BlockParseException(this.type, String.format("protobuf<%s>", pclass.getSimpleName()));
}
return parsed;
}
private void parseTypeCheck(String ... rtypes) {
for (String r : rtypes) {
if (r.equals(type)) return;
}
throw new BlockParseException(type, rtypes);
}
@SuppressWarnings("serial")
public static class BlockParseException extends RuntimeException {
public BlockParseException(String type, String ... rtype) {
super(String.format("Block of type '%s' cannot be parsed as any of '%s'",
type, Arrays.toString(rtype)));
}
}
}