package com.millistream.www;

import java.util.ArrayList;
import com.millistream.www.fields.M;
import com.millistream.www.fields.MC;
import com.millistream.www.fields.DLY;

/**
 * This class represents the header of a message received from the server.
 * 
 * @author Liang Qu
 * @version 0.1, 03/25/10
 * @see com.millistream.www.fields.M
 * @see com.millistream.www.fields.MC
 */
public class MessageHeader {
	private final short mref;
	private final long mclass;
	private final long insref;
	private final short delay;
	private ArrayList<MessageField> fields;

	/**
	 * Constructs a new <code>MessageHeader</code> object.
	 * 
	 * @param mref
	 *            message reference
	 * @param mclass
	 *            message class
	 * @param insref
	 *            instrument reference
	 */
	public MessageHeader(short mref, long mclass, long insref, short delay) {
		this.mref = mref;
		this.mclass = mclass;
		this.insref = insref;
		this.delay = delay;
	}

	/**
	 * Constructs a new <code>MessageHeader</code> object with all the fields.
	 * 
	 * @param mref
	 *            message reference
	 * @param mclass
	 *            message class
	 * @param insref
	 *            instrument reference
	 * @param fields
	 *            an ArrayList of the fields
	 */
	public MessageHeader(short mref, long mclass, long insref, short delay, ArrayList<MessageField> fields) {
		this.mref = mref;
		this.mclass = mclass;
		this.insref = insref;
		this.delay = delay;
		this.fields = fields;
	}

	/**
	 * Returns the Message Reference
	 *
	 * @return the mref
	*/
	public short getMref() {
		return mref;
	}

	/**
	 * Returns the Message Class
	 *
	 * @return the mclass
	*/
	public long getMclass() {
		return mclass;
	}

	/**
	 * Returns the intended delay of the message, will only contain 0 unless the connection is set to delay-mode using <code>setHandleDelay</code>
	 *
	 * @return the intended delay of the message
	*/
	public short getDelay() {
		return delay;
	}

	/**
	 * Returns the Instrument Reference (insref)
	 *
	 * @return the insref
	*/
	public long getInsref() {
		return insref;
	}

	/**
	 * Returns an ArrayList of the fields. Only works if the MessageHeader was returned by a call to the getMessagesAndFields() method.
	 *
	 * @return a ArrayList object with all the fields for this message
	*/
	public ArrayList<MessageField> getFields() {
		return fields;
	}

	/**
	 * Constructs and returns a (debug) String of the Mref, Mclass and Insref
	 *
	*/
	public String toString() {
		String mrefStr = null;
		String mclassStr = null;
		String delayStr = null;

		switch (mref) {
		case M.MESSAGESREFERENCE:
			mrefStr = "M.MESSAGESREFERENCE";
			break;
		case M.LOGON:
			mrefStr = "M.LOGON";
			break;
		case M.LOGOFF:
			mrefStr = "M.LOGOFF";
			break;
		case M.LOGONGREETING:
			mrefStr = "M.LOGONGREETING";
			break;
		case M.NEWSHEADLINE:
			mrefStr = "M.NEWSHEADLINE";
			break;
		case M.QUOTE:
			mrefStr = "M.QUOTE";
			break;
		case M.TRADE:
			mrefStr = "M.TRADE";
			break;
		case M.BIDLEVELINSERT:
			mrefStr = "M.BIDLEVELINSERT";
			break;
		case M.ASKLEVELINSERT:
			mrefStr = "M.ASKLEVELINSERT";
			break;
		case M.BIDLEVELDELETE:
			mrefStr = "M.BIDLEVELDELETE";
			break;
		case M.ASKLEVELDELETE:
			mrefStr = "M.ASKLEVELDELETE";
			break;
		case M.BIDLEVELUPDATE:
			mrefStr = "M.BIDLEVELUPDATE";
			break;
		case M.ASKLEVELUPDATE:
			mrefStr = "M.ASKLEVELUPDATE";
			break;
		case M.INSTRUMENTRESET:
			mrefStr = "M.INSTRUMENTRESET";
			break;
		case M.ORDERBOOKFLUSH:
			mrefStr = "M.ORDERBOOKFLUSH";
			break;
		case M.BASICDATA:
			mrefStr = "M.BASICDATA";
			break;
		case M.PRICEHISTORY:
			mrefStr = "M.PRICEHISTORY";
			break;
		case M.INSTRUMENTDELETE:
			mrefStr = "M.INSTRUMENTDELETE";
			break;
		case M.FIELDSREFERENCE:
			mrefStr = "M.FIELDSREFERENCE";
			break;
		case M.REQUEST:
			mrefStr = "M.REQUEST";
			break;
		case M.REQUESTFINISHED:
			mrefStr = "M.REQUESTFINISHED";
			break;
		case M.INSREF:
			mrefStr = "M.INSREF";
			break;
		case M.NEWSCONTENT:
			mrefStr = "M.NEWSCONTENT";
			break;
		case M.TRADESTATE:
			mrefStr = "M.TRADESTATE";
			break;
		case M.PERFORMANCE:
			mrefStr = "M.PERFORMANCE";
			break;
		case M.KEYRATIOS:
			mrefStr = "M.KEYRATIOS";
			break;
		case M.ESTIMATES:
			mrefStr = "M.ESTIMATES";
			break;
		case M.ESTIMATESHISTORY:
			mrefStr = "M.ESTIMATESHISTORY";
			break;
		case M.NETORDERIMBALANCE:
			mrefStr = "M.NETORDERIMBALANCE";
			break;
		case M.L10N:
			mrefStr = "M.L10N";
			break;
		case M.CI:
			mrefStr = "M.CI";
			break;
		case M.CIHISTORY:
			mrefStr = "M.CIHISTORY";
			break;
		case M.PRIIP:
			mrefStr = "M.PRIIP";
			break;
		case M.MIFID:
			mrefStr = "M.MIFID";
			break;
		case M.MIFIDHISTORY:
			mrefStr = "M.MIFIDHISTORY";
			break;
		case M.MAPPINGS:
			mrefStr = "M.MAPPINGS";
			break;
		case M.MBOADD:
			mrefStr = "M.MBOADD";
			break;
		case M.MBOUPDATE:
			mrefStr = "M.MBOUPDATE";
			break;
		case M.MBODELETE:
			mrefStr = "M.MBODELETE";
			break;
		case M.GREEKS:
			mrefStr = "M.GREEKS";
			break;
		case M.QUOTEBBO:
			mrefStr = "M.QUOTEBBO";
			break;
		case M.QUOTEEX:
			mrefStr = "M.QUOTEEX";
			break;

		default:
			mrefStr = "unknown[" + mref + "]";
			break;
		}

		if (mclass == MC.UNDEF)
			mclassStr = " MC.UNDEF";
		else
			mclassStr = "";

		if ((mclass & MC.NEWSHEADLINE)      == MC.NEWSHEADLINE)      mclassStr += (" MDF_MC_NEWSHEADLINE");
		if ((mclass & MC.QUOTE)             == MC.QUOTE)             mclassStr += (" MDF_MC_QUOTE");
		if ((mclass & MC.TRADE)             == MC.TRADE)             mclassStr += (" MDF_MC_TRADE");
		if ((mclass & MC.ORDER)             == MC.ORDER)             mclassStr += (" MDF_MC_ORDER");
		if ((mclass & MC.BASICDATA)         == MC.BASICDATA)         mclassStr += (" MDF_MC_BASICDATA");
		if ((mclass & MC.PRICEHISTORY)      == MC.PRICEHISTORY)      mclassStr += (" MDF_MC_PRICEHISTORY");
		if ((mclass & MC.NEWSCONTENT)       == MC.NEWSCONTENT)       mclassStr += (" MDF_MC_NEWSCONTENT");
		if ((mclass & MC.TRADESTATE)        == MC.TRADESTATE)        mclassStr += (" MDF_MC_TRADESTATE");
		if ((mclass & MC.FUNDAMENTALS)      == MC.FUNDAMENTALS)      mclassStr += (" MDF_MC_FUNDAMENTALS");
		if ((mclass & MC.PERFORMANCE)       == MC.PERFORMANCE)       mclassStr += (" MDF_MC_PERFORMANCE");
		if ((mclass & MC.KEYRATIOS)         == MC.KEYRATIOS)         mclassStr += (" MDF_MC_KEYRATIOS");
		if ((mclass & MC.ESTIMATES)         == MC.ESTIMATES)         mclassStr += (" MDF_MC_ESTIMATES");
		if ((mclass & MC.ESTIMATESHISTORY)  == MC.ESTIMATESHISTORY)  mclassStr += (" MDF_MC_ESTIMATESHSITORY");
		if ((mclass & MC.NETORDERIMBALANCE) == MC.NETORDERIMBALANCE) mclassStr += (" MDF_MC_NETORDERIMBALANCE");
		if ((mclass & MC.L10N)              == MC.L10N)              mclassStr += (" MDF_MC_L10N");
		if ((mclass & MC.CI)                == MC.CI)                mclassStr += (" MDF_MC_CI");
		if ((mclass & MC.CIHISTORY)         == MC.CIHISTORY)         mclassStr += (" MDF_MC_CIHISTORY");
		if ((mclass & MC.PRIIP)             == MC.PRIIP)             mclassStr += (" MDF_MC_PRIIP");
		if ((mclass & MC.MIFID)             == MC.MIFID)             mclassStr += (" MDF_MC_MIFID");
		if ((mclass & MC.MIFIDHISTORY)      == MC.MIFIDHISTORY)      mclassStr += (" MDF_MC_MIFIDHISTORY");
		if ((mclass & MC.MAPPINGS)          == MC.MAPPINGS)          mclassStr += (" MDF_MC_MAPPINGS");
		if ((mclass & MC.MBO)               == MC.MBO)               mclassStr += (" MDF_MC_MBO");
		if ((mclass & MC.GREEKS )           == MC.GREEKS )           mclassStr += (" MDF_MC_GREEKS");
		if ((mclass & MC.QUOTEBBO)          == MC.QUOTEBBO)          mclassStr += (" MDF_MC_QUOTEBBO");
		if ((mclass & MC.QUOTEEX)           == MC.QUOTEEX)           mclassStr += (" MDF_MC_QUOTEEX");

		switch (delay) {
			case DLY.REALTIME : delayStr = "DLY.REALTIME"; break;
			case DLY.DELAY    : delayStr = "DLY.DELAY"; break;
			case DLY.EOD      : delayStr = "DLY.EOD"; break;
			case DLY.NEXTDAY  : delayStr = "DLY.NEXTDAY"; break;
			case DLY.T1       : delayStr = "DLY.T1"; break;
			case DLY.ANY      : delayStr = "DLY.ANY"; break;
			case DLY.BEST     : delayStr = "DLY.BEST"; break;
		}

		return "mref=" + mrefStr + "[" + mref + "], mclass=" + mclassStr + "["
				+ mclass + "], insref=" + insref
				+ ", delay=" + delayStr + "[" + delay + "]";
		// return "mref=" + mref + ", mclass=" + mclass + ", insref=" + insref;
	}
}
