/*
 * 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 {

    // TODO should be an enum
    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();
    }

    /**
     * Gets the IGMP record type.
     *
     * @return record type
     */
    public byte getRecordType() {
        return recordType;
    }

    /**
     * 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());


        for (; nsrcs > 0; nsrcs--) {
            // Make sure we have enough buffer to hold all of these sources
            checkBufferLength(bb.remaining(), 0, Ip4Address.BYTE_LENGTH * 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;
    }
}
