package org.projectfloodlight.openflow.types;

import javax.annotation.Nullable;

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

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 Logger logger = LoggerFactory.getLogger(OFVlanVidMatch.class);

    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 == UNTAGGED_VAL_OF10) {
            // workaround for IVS sometimes sending 0F1.0 untagged (0xFFFF) values
            logger.warn("Warning: received OF1.0 untagged vlan value (0xFFFF) in OF1.3 VlanVid. Treating as UNTAGGED");
            return UNTAGGED;
        } 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);
    }
}
