/*
 * Copyright 2015 Open Networking Laboratory
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.onlab.packet;

import java.nio.ByteBuffer;
import static org.onlab.packet.PacketUtils.checkBufferLength;

public class IGMPMembership extends IGMPGroup {

    public static final byte MODE_IS_INCLUDE = 0x1;
    public static final byte MODE_IS_EXCLUDE = 0x2;
    public static final byte CHANGE_TO_INCLUDE_MODE = 0x3;
    public static final byte CHANGE_TO_EXCLUDE_MODE = 0x4;
    public static final byte ALLOW_NEW_SOURCES = 0x5;
    public static final byte BLOCK_OLD_SOURCES = 0x6;

    private final int minGroupRecordLen = Ip4Address.BYTE_LENGTH + 4;

    protected byte recordType;
    protected byte auxDataLength = 0;
    protected byte[] auxData;

    /**
     * Constructor initialized with a multicast group address.
     *
     * @param gaddr A multicast group address.
     */
    public IGMPMembership(Ip4Address gaddr) {
        super(gaddr, 0);
    }

    /**
     * Default constructor.
     */
    public IGMPMembership() {
        super();
    }

    /**
     * Serialize this Membership Report.
     *
     * @param bb the ByteBuffer to write into, positioned at the next spot to be written to.
     * @return serialized IGMP message.
     */
    @Override
    public byte[] serialize(ByteBuffer bb) {

        bb.put(recordType);
        bb.put(auxDataLength);      // reserved
        bb.putShort((short) sources.size());
        bb.put(gaddr.toOctets());
        for (IpAddress ipaddr : sources) {
            bb.put(ipaddr.toOctets());
        }

        if (auxDataLength > 0) {
            bb.put(auxData);
        }

        return bb.array();
    }

    /**
     * Deserialize the IGMP Membership report packet.
     *
     * @param bb the ByteBuffer wrapping the serialized message.  The position of the
     *           ByteBuffer should be pointing at the head of either message type.
     * @return IGMP Group
     * @throws DeserializationException if deserialization fails
     */
    public IGMPGroup deserialize(ByteBuffer bb) throws DeserializationException {

        // Make sure there is enough buffer to read the header,
        // including the number of sources
        checkBufferLength(bb.remaining(), 0, minGroupRecordLen);
        recordType = bb.get();
        auxDataLength = bb.get();
        int nsrcs = bb.getShort();

        gaddr = Ip4Address.valueOf(bb.getInt());

        // Make sure we have enough buffer to hold all of these sources
        checkBufferLength(bb.remaining(), 0, Ip4Address.BYTE_LENGTH * nsrcs);
        for (; nsrcs > 0; nsrcs--) {
            Ip4Address src = Ip4Address.valueOf(bb.getInt());
            this.sources.add(src);
        }

        if (auxDataLength > 0) {
            auxData = new byte[auxDataLength];
            bb.get(auxData, 0, auxDataLength);
        }
        return this;
    }

    /*
     * (non-Javadoc)
     *
     * @see java.lang.Object#equals()
     */
    public boolean equals(Object obj) {
        if (this == obj) {
            return true;
        }
        if (!(obj instanceof IGMPMembership)) {
            return false;
        }
        IGMPMembership other = (IGMPMembership) obj;

        if (!this.gaddr.equals(other.gaddr)) {
            return false;
        }
        if (this.recordType != other.recordType) {
            return false;
        }
        if (this.auxDataLength != other.auxDataLength) {
            return false;
        }
        if (this.sources.size() != other.sources.size()) {
            return false;
        }
        // TODO: make these tolerant of order
        if (!this.sources.equals(other.sources)) {
            return false;
        }

        return true;
    }

    /*
     * (non-Javadoc)
     *
     * @see java.lang.Object#hashCode()
     */
    @Override
    public int hashCode() {
        final int prime = 2521;
        int result = super.hashCode();
        result = prime * result + this.gaddr.hashCode();
        result = prime * result + this.recordType;
        result = prime * result + this.auxDataLength;
        result = prime * result + this.sources.hashCode();
        return result;
    }
}
