package server;

public class Message {
	public static final byte[] MAGIC = { 1, 3, 3, 7 };

	/* MUST start with 0 and MUST end with MSG_LAST_MSG, and MUST be contiguous */
	public static final byte MSG_YOURTURN = 0;
	public static final byte MSG_READY = 1;
	public static final byte MSG_UNREADY = 2;
	public static final byte MSG_INVALID = 3; //FIXME first, fix all other errors (META_MOVE_INVALID)
	public static final byte MSG_VALID = 4; //FIXME first, fix all other errors (META_MOVE_VALID)
	public static final byte MSG_WON = 5;
	public static final byte MSG_LOST = 6;
	public static final byte MSG_LEAVE = 7;
	public static final byte MSG_CONNECTION_VALID = 8;
	public static final byte MSG_CONNECTION_INVALID = 9;
	public static final byte MSG_MOVE = 10;
	public static final byte MSG_UPDATE = 11;
	public static final byte MSG_LAST_MSG = MSG_UPDATE;
	
	private static void throwOnInvalidMsgType(byte b) {
		if(b < 0 || b > MSG_LAST_MSG) throw new RuntimeException("Invalid message Type " + b + ".");
	}

	private byte msgType;

	private Move move;

	private int ownId;

	public Message(byte msgType) {
		throwOnInvalidMsgType(msgType);
		setMsgType(msgType);
	}

	public Message(Move m) {
		setMsgType(MSG_MOVE);
		move = m; // TODO: clone?
	}

	//public Message(JSONObject jo) throws JSONException {
		//this.jo = (JSONObject)jo.clone();
		//this.jo = jo; // TODO: clone?
//		moveType = (byte)jo.getInt("msgType");
	//}

//	public static Message newMove(Card c) {
//		try {
//			return new Message(c.toJson());
//		} catch(JSONException ex) {
//			throw new InternalHanabiError(ex);
//		}
//	}

	public Message(byte[] bytes) {
		throw new RuntimeException("Not implemented. This is a bug.");
	}

	public byte[] toBytes() {
		return toBytes(ServerGame.PROTO_VIBE_DUMB);
	}

	public byte[] toBytes(byte proto) {
		switch(proto) {
		case ServerGame.PROTO_VIBE_DUMB:
			throw new RuntimeException("Not implemented. This is a bug.");
		default:
			throw new InternalHanabiError("Message.toBytes(byte) called with invalid protocol code " + proto + ".");
		}
	}

//	public JSONObject getJson() {
//		return jo;
//	}
//	public String toJsonString() {
//		if(jo == null) return "";
//		return jo.toString();
//	}
	public byte getMsgType() {
		return msgType; 
	}

//	public int getOrigin() {
//		return origin;
////		try {
////			return jo.getInt("origin");
////		} catch(JSONException ex) {
////			throw new InternalHanabiError(ex);
////		}
//	}

//	public void setOrigin(int orig) { origin = orig; }

//	public int getHintType() {
//		if(msgType != MSG_MOVE) {
//			throw new RuntimeException("Internal Error: Hint type of non-hint move requested.");
//		}
//		return move.getHintType();
//	}
//	
//	public int getValue() {
//		if(msgType != Move.HINT) {
//			throw new RuntimeException("Internal Error: Hint value of non-hint message requested.");
//		}
//		try {
//			return jo.getInt("value");
//		} catch(JSONException ex) {
//			throw new InternalHanabiError(ex);
//		}
//	}
//	public int getHintRecipient() {
//		if(msgType != Move.HINT) {
//			throw new RuntimeException("Internal Error: Target player ID of non-hint message requested.");
//		}
//		try {
//			return jo.getInt("playerId");
//		} catch(JSONException ex) {
//			throw new InternalHanabiError(ex);
//		}
//	}

	public int getOwnId() {
		if(msgType != MSG_CONNECTION_VALID) {
			throw new RuntimeException("Internal Error: ownId of non-connection valid message requested.");
		}
		return ownId;
	}
	
	public void setOwnId(int id) {
		if(msgType != MSG_CONNECTION_VALID) {
			throw new RuntimeException("Internal Error: Attempt to set ownId of non-connection valid message.");
		}
		ownId = id;
	}

	public static Message makeInvalidMoveAnswer(Message m) {
		return new Message(MSG_INVALID);
	}

	public static Message makeItsYourTurnMessage() {
		return new Message(MSG_YOURTURN);
	}

	public boolean isNonMove() {
		return msgType != MSG_MOVE;
	}

	public void setMsgType(byte msgType) {
		this.msgType = msgType;
	}

	public Move getMove() {
		return move;
	}

	public void setMove(Move move) {
		this.move = move; // TODO clone?
	}
}