/*
 * Copyright 2017-present 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 java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 * Class representing MKPDU Live/Potential Peer List Parameter Set.
 * IEEE 802.1X Clause 11; Figure 11-9
 */
public class EAPOLMkpduPeerListParameterSet extends BasePacket implements EAPOLMkpduParameterSet {

    // Member Details
    public static class MemberDetails {
        byte[] memberID;
        int messageNo;

        public MemberDetails(byte[] memberID, int messageNo) {
            this.memberID = memberID;
            this.messageNo = messageNo;
        }

        public byte[] getMemberID() {
            return memberID;
        }

        public int getMessageNo() {
            return messageNo;
        }
    }

    // Peer List Types
    public static byte peerListTypeLive = 1;
    public static byte peerListTypePotential = 2;

    // Type for distinguishing Live & Potential Lists.
    protected byte peerListType = 1;
    protected short bodyLength;

    //Members
    protected List<MemberDetails> members = new ArrayList<>();

    @Override
    public byte[] serialize() {

        // Don't Serialize if no members are available.
        if (members.size() == 0) {
            return null;
        }

        // Serialize PeerList Parameter Set. IEEE 802.1x, Figure 11.9
        short length = getTotalLength();
        ByteBuffer data = ByteBuffer.wrap(new byte[length]);

        /*
         *Populate fields
         * Octet 1
         */
        data.put(peerListType);

        // Octet 2. Reserved.
        byte octet = 0x00;
        data.put(octet);

        // Octet 3
        length -= EAPOLMkpduParameterSet.BODY_LENGTH_OCTET_OFFSET;
        octet |= (byte) (length >> BODY_LENGTH_MSB_SHIFT & BODY_LENGTH_MSB_MASK);
        data.put(octet);

        // Octet 4
        data.put((byte) length);

        // Member details.
        members.forEach(a -> {
                    data.put(a.getMemberID());
                    data.putInt(a.getMessageNo());
                }
        );

        return data.array();
    }


    /**
     * Deserializer function for Peer List Parameter Set.
     *
     * @return deserializer function
     */
    public static Deserializer<EAPOLMkpduPeerListParameterSet> deserializer() {
        return (data, offset, length) -> {

            // Ensure buffer has enough details.
            if (data == null) {
                return null;
            }

            // Deserialize Basic Parameter Set.
            final ByteBuffer bb = ByteBuffer.wrap(data, offset, length);
            EAPOLMkpduPeerListParameterSet peerListParameterSet =
                    new EAPOLMkpduPeerListParameterSet();

            // Parse Peer List Fields/
            byte[] mbField = new byte[1];
            // mbField[0] = bb.get(); // Skip Type. Already processed in EAPOL-MKPDU de-serializer.
            bb.get(); // Skip Reserved.

            // Length
            mbField[0] = bb.get();
            short bodyLength = (short) (((short) (mbField[0] & EAPOLMkpduParameterSet.BODY_LENGTH_MSB_MASK))
                    << EAPOLMkpduParameterSet.BODY_LENGTH_OCTET_OFFSET);
            bodyLength |= (short) (bb.get());
            peerListParameterSet.setBodyLength(bodyLength);

            // Member details
            while (bodyLength > 0) {
                mbField = new byte[FIELD_MI_LENGTH];
                bb.get(mbField, 0, FIELD_MI_LENGTH);
                peerListParameterSet.addMember(mbField, bb.getInt());
                bodyLength -= FIELD_MI_LENGTH + FIELD_MN_LENGTH;
            }
            return peerListParameterSet;
        };
    }

    /**
     * Setting List Type.
     *
     * @param peerListType type - PEERLIST_TYPE_LIVE or PEERLIST_TYPE_POTENTIAL for live
     *                     and potential peer lists
     */
    public void setPeerListType(byte peerListType) {
        if ((peerListType != EAPOLMkpduPeerListParameterSet.peerListTypeLive) &&
                (peerListType != EAPOLMkpduPeerListParameterSet.peerListTypePotential)) {
            throw new IllegalArgumentException("Unknown PeerList Type specified.");
        }
        this.peerListType = peerListType;
    }

    /**
     * Member details adding.
     *
     * @param mi ,type byte[]
     * @param mn , type int
     */
    public void addMember(byte[] mi, int mn) {
        if (mi != null) {
            members.add(new MemberDetails(mi, mn));
        }
        return;
    }

    /**
     * Searching Member details.
     *
     * @param mi ,type byte[]
     * @return boolean based on the value of member.
     */
    public boolean memberExists(byte[] mi) {
        MemberDetails member = members.stream()
                .filter(m -> Arrays.equals(m.getMemberID(), mi))
                .findAny()
                .orElse(null);
        return (member != null) ? true : false;
    }

    /**
     * Member details.
     *
     * @return members
     */
    public List<MemberDetails> getMembers() {
        return members;
    }

    @Override
    public byte getParameterSetType() {
        return peerListType;
    }

    @Override
    public short getTotalLength() {
        return (short) (EAPOLMkpduParameterSet.BODY_LENGTH_OCTET_OFFSET +
                members.size() * (EAPOLMkpduParameterSet.FIELD_MI_LENGTH +
                        EAPOLMkpduParameterSet.FIELD_MN_LENGTH));
    }

    @Override
    public short getBodyLength() {
        return bodyLength;
    }

    /**
     * Body Length.
     *
     * @param length ,type short
     */
    public void setBodyLength(short length) {
        this.bodyLength = length;
    }
}

