package org.projectfloodlight.openflow.types;

import javax.annotation.Nullable;

import org.jboss.netty.buffer.ChannelBuffer;
import org.projectfloodlight.openflow.exceptions.OFParseError;

import com.google.common.hash.PrimitiveSink;
import com.google.common.primitives.Shorts;

/** Represents an OpenFlow Vlan VID for use in Matches, as specified by the OpenFlow 1.3 spec.
 *
 *  <b> Note: this is not just the 12-bit vlan tag. OpenFlow defines
 *      the additional mask bits 0x1000 to represent the presence of a vlan
 *      tag. This additional bit will be stripped when writing a OF1.0 value
 *      tag.
 *  </b>
 *
 *
 * @author Andreas Wundsam <andreas.wundsam@bigswitch.com>
 *
 */
public class OFVlanVidMatch implements OFValueType<OFVlanVidMatch> {

    private static final short VALIDATION_MASK = 0x1FFF;
    private static final short PRESENT_VAL = 0x1000;
    private static final short VLAN_MASK = 0x0FFF;
    private static final short NONE_VAL = 0x0000;
    private static final short UNTAGGED_VAL_OF13 = (short) 0x0000;
    private static final short UNTAGGED_VAL_OF10 = (short) 0xFFFF;
    final static int LENGTH = 2;

    /** presence of a VLAN tag is indicated by the presence of bit 0x1000 */
    public static final OFVlanVidMatch PRESENT = new OFVlanVidMatch(PRESENT_VAL);

    /** this value means 'not set' in OF1.0 (e.g., in a match). not used elsewhere */
    public static final OFVlanVidMatch NONE = new OFVlanVidMatch(NONE_VAL);

    /** for use with masking operations */
    public static final OFVlanVidMatch NO_MASK = new OFVlanVidMatch((short)0xFFFF);
    public static final OFVlanVidMatch FULL_MASK = NONE;

    /** an untagged packet is specified as 0000 in OF 1.0, but 0xFFFF in OF1.0. Special case that. */
    public static final OFVlanVidMatch UNTAGGED = new OFVlanVidMatch(NONE_VAL) {
        @Override
        public void write2BytesOF10(ChannelBuffer c) {
            c.writeShort(UNTAGGED_VAL_OF10);
        }
    };

    private final short vid;

    private OFVlanVidMatch(short vid) {
        this.vid = vid;
    }

    public static OFVlanVidMatch ofRawVid(short vid) {
        if(vid == UNTAGGED_VAL_OF13)
            return UNTAGGED;
        else if(vid == PRESENT_VAL)
            return PRESENT;
        else if ((vid & VALIDATION_MASK) != vid)
            throw new IllegalArgumentException(String.format("Illegal VLAN value: %x", vid));
        return new OFVlanVidMatch(vid);
    }

    public static OFVlanVidMatch ofVlanVid(VlanVid vid) {
        return ofVlan(vid.getVlan());
    }


    public static OFVlanVidMatch ofVlan(int vlan) {
        if( (vlan & VLAN_MASK) != vlan)
            throw new IllegalArgumentException(String.format("Illegal VLAN value: %x", vlan));
        return ofRawVid( (short) (vlan | PRESENT_VAL));
    }

    public static OFVlanVidMatch ofVlanOF10(short of10vlan) {
        if(of10vlan == NONE_VAL) {
            return NONE;
        } else if(of10vlan == UNTAGGED_VAL_OF10) {
            return UNTAGGED;
        } else {
            return ofVlan(of10vlan);
        }
    }

    /** @return whether or not this VlanId has the present (0x1000) bit set */
    public boolean isPresentBitSet() {
       return (vid & PRESENT_VAL) != 0;
    }

    /** @return the actual VLAN tag this vid identifies */
    public short getVlan() {
        return (short) (vid & VLAN_MASK);
    }

    /** @return the actual vlan tag this vid identifies as a VlanVid object, if this
     *  VlanVidMatch has the present bit set (i.e., identifies a tagged VLAN).
     *  Else, returns null.
     */
    @Nullable
    public VlanVid getVlanVid() {
        return isPresentBitSet() ? VlanVid.ofVlan((short) (vid & VLAN_MASK)) : null;
    }

    @Override
    public boolean equals(Object obj) {
        if (!(obj instanceof OFVlanVidMatch))
            return false;
        OFVlanVidMatch other = (OFVlanVidMatch)obj;
        if (other.vid != this.vid)
            return false;
        return true;
    }

    @Override
    public int hashCode() {
        int prime = 13873;
        return this.vid * prime;
    }

    @Override
    public String toString() {
        return "0x" + Integer.toHexString(vid);
    }

    public short getRawVid() {
        return vid;
    }


    @Override
    public int getLength() {
        return LENGTH;
    }


    volatile byte[] bytesCache = null;

    public byte[] getBytes() {
        if (bytesCache == null) {
            synchronized (this) {
                if (bytesCache == null) {
                    bytesCache =
                            new byte[] { (byte) ((vid >>> 8) & 0xFF),
                                         (byte) ((vid >>> 0) & 0xFF) };
                }
            }
        }
        return bytesCache;
    }

    public void write2Bytes(ChannelBuffer c) {
        c.writeShort(this.vid);
    }

    public void write2BytesOF10(ChannelBuffer c) {
        c.writeShort(this.getVlan());
    }

    public static OFVlanVidMatch read2Bytes(ChannelBuffer c) throws OFParseError {
        return OFVlanVidMatch.ofRawVid(c.readShort());
    }

    public static OFVlanVidMatch read2BytesOF10(ChannelBuffer c) throws OFParseError {
        return OFVlanVidMatch.ofVlanOF10(c.readShort());
    }

    @Override
    public OFVlanVidMatch applyMask(OFVlanVidMatch mask) {
        return OFVlanVidMatch.ofRawVid((short)(this.vid & mask.vid));
    }

    @Override
    public int compareTo(OFVlanVidMatch o) {
        return Shorts.compare(vid, o.vid);
    }
    @Override
    public void putTo(PrimitiveSink sink) {
        sink.putShort(vid);
    }
}
