// Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior University
// Copyright (c) 2011, 2012 Open Networking Foundation
// Copyright (c) 2012, 2013 Big Switch Networks, Inc.
// This library was generated by the LoxiGen Compiler.
// See the file LICENSE.txt which should have been included in the source distribution

// Automatically generated by LOXI from template of_class.java
// Do not modify

package org.projectfloodlight.openflow.protocol.ver13;

import org.projectfloodlight.openflow.protocol.*;
import org.projectfloodlight.openflow.protocol.action.*;
import org.projectfloodlight.openflow.protocol.actionid.*;
import org.projectfloodlight.openflow.protocol.bsntlv.*;
import org.projectfloodlight.openflow.protocol.errormsg.*;
import org.projectfloodlight.openflow.protocol.meterband.*;
import org.projectfloodlight.openflow.protocol.instruction.*;
import org.projectfloodlight.openflow.protocol.instructionid.*;
import org.projectfloodlight.openflow.protocol.match.*;
import org.projectfloodlight.openflow.protocol.oxm.*;
import org.projectfloodlight.openflow.protocol.queueprop.*;
import org.projectfloodlight.openflow.types.*;
import org.projectfloodlight.openflow.util.*;
import org.projectfloodlight.openflow.exceptions.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.List;
import com.google.common.collect.ImmutableList;
import java.util.Set;
import org.jboss.netty.buffer.ChannelBuffer;
import com.google.common.hash.PrimitiveSink;
import com.google.common.hash.Funnel;

class OFBucketVer13 implements OFBucket {
    private static final Logger logger = LoggerFactory.getLogger(OFBucketVer13.class);
    // version: 1.3
    final static byte WIRE_VERSION = 4;
    final static int MINIMUM_LENGTH = 16;

        private final static int DEFAULT_WEIGHT = 0x0;
        private final static OFPort DEFAULT_WATCH_PORT = OFPort.ANY;
        private final static OFGroup DEFAULT_WATCH_GROUP = OFGroup.ALL;
        private final static List<OFAction> DEFAULT_ACTIONS = ImmutableList.<OFAction>of();

    // OF message fields
    private final int weight;
    private final OFPort watchPort;
    private final OFGroup watchGroup;
    private final List<OFAction> actions;
//
    // Immutable default instance
    final static OFBucketVer13 DEFAULT = new OFBucketVer13(
        DEFAULT_WEIGHT, DEFAULT_WATCH_PORT, DEFAULT_WATCH_GROUP, DEFAULT_ACTIONS
    );

    // package private constructor - used by readers, builders, and factory
    OFBucketVer13(int weight, OFPort watchPort, OFGroup watchGroup, List<OFAction> actions) {
        this.weight = weight;
        this.watchPort = watchPort;
        this.watchGroup = watchGroup;
        this.actions = actions;
    }

    // Accessors for OF message fields
    @Override
    public int getWeight() {
        return weight;
    }

    @Override
    public OFPort getWatchPort() {
        return watchPort;
    }

    @Override
    public OFGroup getWatchGroup() {
        return watchGroup;
    }

    @Override
    public List<OFAction> getActions() {
        return actions;
    }

    @Override
    public OFVersion getVersion() {
        return OFVersion.OF_13;
    }



    public OFBucket.Builder createBuilder() {
        return new BuilderWithParent(this);
    }

    static class BuilderWithParent implements OFBucket.Builder {
        final OFBucketVer13 parentMessage;

        // OF message fields
        private boolean weightSet;
        private int weight;
        private boolean watchPortSet;
        private OFPort watchPort;
        private boolean watchGroupSet;
        private OFGroup watchGroup;
        private boolean actionsSet;
        private List<OFAction> actions;

        BuilderWithParent(OFBucketVer13 parentMessage) {
            this.parentMessage = parentMessage;
        }

    @Override
    public int getWeight() {
        return weight;
    }

    @Override
    public OFBucket.Builder setWeight(int weight) {
        this.weight = weight;
        this.weightSet = true;
        return this;
    }
    @Override
    public OFPort getWatchPort() {
        return watchPort;
    }

    @Override
    public OFBucket.Builder setWatchPort(OFPort watchPort) {
        this.watchPort = watchPort;
        this.watchPortSet = true;
        return this;
    }
    @Override
    public OFGroup getWatchGroup() {
        return watchGroup;
    }

    @Override
    public OFBucket.Builder setWatchGroup(OFGroup watchGroup) {
        this.watchGroup = watchGroup;
        this.watchGroupSet = true;
        return this;
    }
    @Override
    public List<OFAction> getActions() {
        return actions;
    }

    @Override
    public OFBucket.Builder setActions(List<OFAction> actions) {
        this.actions = actions;
        this.actionsSet = true;
        return this;
    }
    @Override
    public OFVersion getVersion() {
        return OFVersion.OF_13;
    }



        @Override
        public OFBucket build() {
                int weight = this.weightSet ? this.weight : parentMessage.weight;
                OFPort watchPort = this.watchPortSet ? this.watchPort : parentMessage.watchPort;
                if(watchPort == null)
                    throw new NullPointerException("Property watchPort must not be null");
                OFGroup watchGroup = this.watchGroupSet ? this.watchGroup : parentMessage.watchGroup;
                if(watchGroup == null)
                    throw new NullPointerException("Property watchGroup must not be null");
                List<OFAction> actions = this.actionsSet ? this.actions : parentMessage.actions;
                if(actions == null)
                    throw new NullPointerException("Property actions must not be null");

                //
                return new OFBucketVer13(
                    weight,
                    watchPort,
                    watchGroup,
                    actions
                );
        }

    }

    static class Builder implements OFBucket.Builder {
        // OF message fields
        private boolean weightSet;
        private int weight;
        private boolean watchPortSet;
        private OFPort watchPort;
        private boolean watchGroupSet;
        private OFGroup watchGroup;
        private boolean actionsSet;
        private List<OFAction> actions;

    @Override
    public int getWeight() {
        return weight;
    }

    @Override
    public OFBucket.Builder setWeight(int weight) {
        this.weight = weight;
        this.weightSet = true;
        return this;
    }
    @Override
    public OFPort getWatchPort() {
        return watchPort;
    }

    @Override
    public OFBucket.Builder setWatchPort(OFPort watchPort) {
        this.watchPort = watchPort;
        this.watchPortSet = true;
        return this;
    }
    @Override
    public OFGroup getWatchGroup() {
        return watchGroup;
    }

    @Override
    public OFBucket.Builder setWatchGroup(OFGroup watchGroup) {
        this.watchGroup = watchGroup;
        this.watchGroupSet = true;
        return this;
    }
    @Override
    public List<OFAction> getActions() {
        return actions;
    }

    @Override
    public OFBucket.Builder setActions(List<OFAction> actions) {
        this.actions = actions;
        this.actionsSet = true;
        return this;
    }
    @Override
    public OFVersion getVersion() {
        return OFVersion.OF_13;
    }

//
        @Override
        public OFBucket build() {
            int weight = this.weightSet ? this.weight : DEFAULT_WEIGHT;
            OFPort watchPort = this.watchPortSet ? this.watchPort : DEFAULT_WATCH_PORT;
            if(watchPort == null)
                throw new NullPointerException("Property watchPort must not be null");
            OFGroup watchGroup = this.watchGroupSet ? this.watchGroup : DEFAULT_WATCH_GROUP;
            if(watchGroup == null)
                throw new NullPointerException("Property watchGroup must not be null");
            List<OFAction> actions = this.actionsSet ? this.actions : DEFAULT_ACTIONS;
            if(actions == null)
                throw new NullPointerException("Property actions must not be null");


            return new OFBucketVer13(
                    weight,
                    watchPort,
                    watchGroup,
                    actions
                );
        }

    }


    final static Reader READER = new Reader();
    static class Reader implements OFMessageReader<OFBucket> {
        @Override
        public OFBucket readFrom(ChannelBuffer bb) throws OFParseError {
            int start = bb.readerIndex();
            int length = U16.f(bb.readShort());
            if(length < MINIMUM_LENGTH)
                throw new OFParseError("Wrong length: Expected to be >= " + MINIMUM_LENGTH + ", was: " + length);
            if(bb.readableBytes() + (bb.readerIndex() - start) < length) {
                // Buffer does not have all data yet
                bb.readerIndex(start);
                return null;
            }
            if(logger.isTraceEnabled())
                logger.trace("readFrom - length={}", length);
            int weight = U16.f(bb.readShort());
            OFPort watchPort = OFPort.read4Bytes(bb);
            OFGroup watchGroup = OFGroup.read4Bytes(bb);
            // pad: 4 bytes
            bb.skipBytes(4);
            List<OFAction> actions = ChannelUtils.readList(bb, length - (bb.readerIndex() - start), OFActionVer13.READER);

            OFBucketVer13 bucketVer13 = new OFBucketVer13(
                    weight,
                      watchPort,
                      watchGroup,
                      actions
                    );
            if(logger.isTraceEnabled())
                logger.trace("readFrom - read={}", bucketVer13);
            return bucketVer13;
        }
    }

    public void putTo(PrimitiveSink sink) {
        FUNNEL.funnel(this, sink);
    }

    final static OFBucketVer13Funnel FUNNEL = new OFBucketVer13Funnel();
    static class OFBucketVer13Funnel implements Funnel<OFBucketVer13> {
        private static final long serialVersionUID = 1L;
        @Override
        public void funnel(OFBucketVer13 message, PrimitiveSink sink) {
            // FIXME: skip funnel of length
            sink.putInt(message.weight);
            message.watchPort.putTo(sink);
            message.watchGroup.putTo(sink);
            // skip pad (4 bytes)
            FunnelUtils.putList(message.actions, sink);
        }
    }


    public void writeTo(ChannelBuffer bb) {
        WRITER.write(bb, this);
    }

    final static Writer WRITER = new Writer();
    static class Writer implements OFMessageWriter<OFBucketVer13> {
        @Override
        public void write(ChannelBuffer bb, OFBucketVer13 message) {
            int startIndex = bb.writerIndex();
            // length is length of variable message, will be updated at the end
            int lengthIndex = bb.writerIndex();
            bb.writeShort(U16.t(0));

            bb.writeShort(U16.t(message.weight));
            message.watchPort.write4Bytes(bb);
            message.watchGroup.write4Bytes(bb);
            // pad: 4 bytes
            bb.writeZero(4);
            ChannelUtils.writeList(bb, message.actions);

            // update length field
            int length = bb.writerIndex() - startIndex;
            bb.setShort(lengthIndex, length);

        }
    }

    @Override
    public String toString() {
        StringBuilder b = new StringBuilder("OFBucketVer13(");
        b.append("weight=").append(weight);
        b.append(", ");
        b.append("watchPort=").append(watchPort);
        b.append(", ");
        b.append("watchGroup=").append(watchGroup);
        b.append(", ");
        b.append("actions=").append(actions);
        b.append(")");
        return b.toString();
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        OFBucketVer13 other = (OFBucketVer13) obj;

        if( weight != other.weight)
            return false;
        if (watchPort == null) {
            if (other.watchPort != null)
                return false;
        } else if (!watchPort.equals(other.watchPort))
            return false;
        if (watchGroup == null) {
            if (other.watchGroup != null)
                return false;
        } else if (!watchGroup.equals(other.watchGroup))
            return false;
        if (actions == null) {
            if (other.actions != null)
                return false;
        } else if (!actions.equals(other.actions))
            return false;
        return true;
    }

    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;

        result = prime * result + weight;
        result = prime * result + ((watchPort == null) ? 0 : watchPort.hashCode());
        result = prime * result + ((watchGroup == null) ? 0 : watchGroup.hashCode());
        result = prime * result + ((actions == null) ? 0 : actions.hashCode());
        return result;
    }

}
