/*
 *
 *  * Copyright 2015 AT&T Foundry
 *  *
 *  * 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 com.google.common.base.MoreObjects.toStringHelper;
import static org.onlab.packet.PacketUtils.checkHeaderLength;
import static org.onlab.packet.PacketUtils.checkInput;

/**
 * EAPOL (Extensible Authentication Protocol over LAN) header.
 */
public class EAPOL extends BasePacket {

    private byte version = 0x01;
    private byte eapolType;
    private short packetLength;

    private static final int HEADER_LENGTH = 4;

    // EAPOL Packet Type
    public static final byte EAPOL_PACKET = 0x0;
    public static final byte EAPOL_START  = 0x1;
    public static final byte EAPOL_LOGOFF = 0x2;
    public static final byte EAPOL_KEY    = 0x3;
    public static final byte EAPOL_ASF    = 0x4;

    public static final MacAddress PAE_GROUP_ADDR = MacAddress.valueOf(new byte[] {
            (byte) 0x01, (byte) 0x80, (byte) 0xc2, (byte) 0x00, (byte) 0x00, (byte) 0x03
    });

    /**
     * Gets the version.
     *
     * @return version
     */
    public byte getVersion() {
        return this.version;
    }

    /**
     * Sets the version.
     *
     * @param version EAPOL version
     * @return this
     */
    public EAPOL setVersion(final byte version) {
        this.version = version;
        return this;
    }

    /**
     * Gets the type.
     *
     * @return EAPOL type
     */
    public byte getEapolType() {
        return this.eapolType;
    }

    /**
     * Sets the EAPOL type.
     *
     * @param eapolType EAPOL type
     * @return this
     */
    public EAPOL setEapolType(final byte eapolType) {
        this.eapolType = eapolType;
        return this;
    }

    /**
     * Gets the packet length.
     *
     * @return packet length
     */
    public short getPacketLength() {
        return this.packetLength;
    }

    /**
     * Sets the packet length.
     *
     * @param packetLen packet length
     * @return this
     */
    public EAPOL setPacketLength(final short packetLen) {
        this.packetLength = packetLen;
        return this;
    }

    /**
     * Serializes the packet, based on the code/type using the payload
     * to compute its length.
     *
     * @return this
     */
    @Override
    public byte[] serialize() {
        byte[] payloadData = null;

        if (this.payload != null) {
            this.payload.setParent(this);
            payloadData = this.payload.serialize();
        }

        // prepare the buffer to hold the version (1), packet type (1),
        // packet length (2) and the eap payload.
        // if there is no payload, packet length is 0
        byte[] data = new byte[4 + this.packetLength];
        final ByteBuffer bb = ByteBuffer.wrap(data);
        bb.put(this.version);
        bb.put(this.eapolType);
        bb.putShort(this.packetLength);

        // put the EAP payload
        if (payloadData != null) {
            bb.put(payloadData);
        }

        return data;
    }

    @Override
    public int hashCode() {
        final int prime = 3889;
        int result = super.hashCode();
        result = prime * result + this.version;
        result = prime * result + this.eapolType;
        result = prime * result + this.packetLength;
        return result;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) {
            return true;
        }
        if (!(o instanceof EAPOL)) {
            return false;
        }
        EAPOL that = (EAPOL) o;

        if (this.version != that.version) {
            return false;
        }
        if (this.eapolType != that.eapolType) {
            return false;
        }
        if (this.packetLength != that.packetLength) {
            return false;
        }
        return true;
    }

    /**
     * Deserializer for EAPOL packets.
     *
     * @return deserializer
     */
    public static Deserializer<EAPOL> deserializer() {
        return (data, offset, length) -> {
            checkInput(data, offset, length, HEADER_LENGTH);

            EAPOL eapol = new EAPOL();
            final ByteBuffer bb = ByteBuffer.wrap(data, offset, length);
            eapol.setVersion(bb.get());
            eapol.setEapolType(bb.get());
            eapol.setPacketLength(bb.getShort());

            if (eapol.packetLength > 0) {
                checkHeaderLength(length, HEADER_LENGTH + eapol.packetLength);
                // deserialize the EAP Payload
                eapol.payload = EAP.deserializer().deserialize(data,
                        bb.position(), bb.limit() - bb.position());

                eapol.payload.setParent(eapol);
            }

            return eapol;
        };
    }

    @Override
    public IPacket deserialize(final byte[] data, final int offset,
                               final int length) {
        final ByteBuffer bb = ByteBuffer.wrap(data, offset, length);

        // deserialize the EAPOL header
        this.version = bb.get();
        this.eapolType = bb.get();
        this.packetLength = bb.getShort();

        if (this.packetLength > 0) {
            // deserialize the EAP Payload
            this.payload = new EAP();

            this.payload = this.payload.deserialize(data, bb.position(), length - 4);
            this.payload.setParent(this);
        }

        return this;
    }

    @Override
    public String toString() {
        return toStringHelper(getClass())
                .add("version", Byte.toString(version))
                .add("eapolType", Byte.toString(eapolType))
                .add("packetLength", Short.toString(packetLength))
                .toString();
    }
}

