/*
 *
 *  * 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 org.slf4j.Logger;

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.security.SecureRandom;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import static com.google.common.base.MoreObjects.toStringHelper;
import static org.onlab.packet.PacketUtils.checkHeaderLength;
import static org.onlab.packet.PacketUtils.checkInput;
import static org.slf4j.LoggerFactory.getLogger;

/**
 * RADIUS packet.
 */
public class RADIUS extends BasePacket {
    protected byte code;
    protected byte identifier;
    protected short length = RADIUS_MIN_LENGTH;
    protected byte[] authenticator = new byte[16];
    protected List<RADIUSAttribute> attributes = new ArrayList<>();

    // RADIUS parameters
    public static final short RADIUS_MIN_LENGTH = 20;
    public static final short MAX_ATTR_VALUE_LENGTH = 253;
    public static final short RADIUS_MAX_LENGTH = 4096;

    // RADIUS packet types
    public static final byte RADIUS_CODE_ACCESS_REQUEST = 0x01;
    public static final byte RADIUS_CODE_ACCESS_ACCEPT = 0x02;
    public static final byte RADIUS_CODE_ACCESS_REJECT = 0x03;
    public static final byte RADIUS_CODE_ACCOUNTING_REQUEST = 0x04;
    public static final byte RADIUS_CODE_ACCOUNTING_RESPONSE = 0x05;
    public static final byte RADIUS_CODE_ACCESS_CHALLENGE = 0x0b;

    private final Logger log = getLogger(getClass());

    /**
     * Default constructor.
     */
    public RADIUS() {
    }

    /**
     * Constructs a RADIUS packet with the given code and identifier.
     *
     * @param code       code
     * @param identifier identifier
     */
    public RADIUS(byte code, byte identifier) {
        this.code = code;
        this.identifier = identifier;
    }

    /**
     * Gets the code.
     *
     * @return code
     */
    public byte getCode() {
        return this.code;
    }

    /**
     * Sets the code.
     *
     * @param code code
     */
    public void setCode(byte code) {
        this.code = code;
    }

    /**
     * Gets the identifier.
     *
     * @return identifier
     */
    public byte getIdentifier() {
        return this.identifier;
    }

    /**
     * Get the identifier in a readable format.
     *
     * @return identifier
     */
    public int getReadableIdentifier() {
        return this.identifier & 0xff;
    }

    /**
     * Sets the identifier.
     *
     * @param identifier identifier
     */
    public void setIdentifier(byte identifier) {
        this.identifier = identifier;
    }

    /**
     * Gets the authenticator.
     *
     * @return authenticator
     */
    public byte[] getAuthenticator() {
        return this.authenticator;
    }

    /**
     * Sets the authenticator.
     *
     * @param authenticator authenticator
     */
    public void setAuthenticator(byte[] authenticator) {
        this.authenticator = authenticator;
    }

    /**
     * Generates an authenticator code.
     *
     * @return the authenticator
     */
    public byte[] generateAuthCode() {
        new SecureRandom().nextBytes(this.authenticator);
        return this.authenticator;
    }

    /**
     * Checks if the packet's code field is valid.
     *
     * @return whether the code is valid
     */
    public boolean isValidCode() {
        return this.code == RADIUS_CODE_ACCESS_REQUEST ||
                this.code == RADIUS_CODE_ACCESS_ACCEPT ||
                this.code == RADIUS_CODE_ACCESS_REJECT ||
                this.code == RADIUS_CODE_ACCOUNTING_REQUEST ||
                this.code == RADIUS_CODE_ACCOUNTING_RESPONSE ||
                this.code == RADIUS_CODE_ACCESS_CHALLENGE;
    }

    /**
     * Adds a message authenticator to the packet based on the given key.
     *
     * @param key key to generate message authenticator
     * @return the messgae authenticator RADIUS attribute
     */
    public RADIUSAttribute addMessageAuthenticator(String key) {
        // Message-Authenticator = HMAC-MD5 (Type, Identifier, Length,
        // Request Authenticator, Attributes)
        // When the message integrity check is calculated the signature string
        // should be considered to be sixteen octets of zero.
        byte[] hashOutput = new byte[16];
        Arrays.fill(hashOutput, (byte) 0);

        RADIUSAttribute authAttribute = this.getAttribute(RADIUSAttribute.RADIUS_ATTR_MESSAGE_AUTH);
        if (authAttribute != null) {
            // If Message-Authenticator was already present, override it
            this.log.warn("Attempted to add duplicate Message-Authenticator");
            authAttribute = this.updateAttribute(RADIUSAttribute.RADIUS_ATTR_MESSAGE_AUTH, hashOutput);
        } else {
            // Else generate a new attribute padded with zeroes
            authAttribute = this.setAttribute(RADIUSAttribute.RADIUS_ATTR_MESSAGE_AUTH, hashOutput);
        }
        // Calculate the MD5 HMAC based on the message
        try {
            SecretKeySpec keySpec = new SecretKeySpec(key.getBytes(), "HmacMD5");
            Mac mac = Mac.getInstance("HmacMD5");
            mac.init(keySpec);
            hashOutput = mac.doFinal(this.serialize());
            // Update HMAC in Message-Authenticator
            authAttribute = this.updateAttribute(RADIUSAttribute.RADIUS_ATTR_MESSAGE_AUTH, hashOutput);
        } catch (Exception e) {
            this.log.error("Failed to generate message authenticator: {}", e.getMessage());
        }

        return authAttribute;
    }

    /**
     * Checks the message authenticator in the packet with one generated from
     * the given key.
     *
     * @param key key to generate message authenticator
     * @return whether the message authenticators match or not
     */
    public boolean checkMessageAuthenticator(String key) {
        byte[] newHash = new byte[16];
        Arrays.fill(newHash, (byte) 0);
        byte[] messageAuthenticator = this.getAttribute(RADIUSAttribute.RADIUS_ATTR_MESSAGE_AUTH).getValue();
        this.updateAttribute(RADIUSAttribute.RADIUS_ATTR_MESSAGE_AUTH, newHash);
        // Calculate the MD5 HMAC based on the message
        try {
            SecretKeySpec keySpec = new SecretKeySpec(key.getBytes(), "HmacMD5");
            Mac mac = Mac.getInstance("HmacMD5");
            mac.init(keySpec);
            newHash = mac.doFinal(this.serialize());
        } catch (Exception e) {
            log.error("Failed to generate message authenticator: {}", e.getMessage());
        }
        this.updateAttribute(RADIUSAttribute.RADIUS_ATTR_MESSAGE_AUTH, messageAuthenticator);
        // Compare the calculated Message-Authenticator with the one in the message
        return Arrays.equals(newHash, messageAuthenticator);
    }

    /**
     * Encapsulates an EAP packet in this RADIUS packet.
     *
     * @param message EAP message object to be embedded in the RADIUS
     *                EAP-Message attributed
     */
    public void encapsulateMessage(EAP message) {
        if (message.length <= MAX_ATTR_VALUE_LENGTH) {
            // Use the regular serialization method as it fits into one EAP-Message attribute
            this.setAttribute(RADIUSAttribute.RADIUS_ATTR_EAP_MESSAGE,
                    message.serialize());
        } else {
            // Segment the message into chucks and embed them in several EAP-Message attributes
            short remainingLength = message.length;
            byte[] messageBuffer = message.serialize();
            final ByteBuffer bb = ByteBuffer.wrap(messageBuffer);
            while (bb.hasRemaining()) {
                byte[] messageAttributeData;
                if (remainingLength > MAX_ATTR_VALUE_LENGTH) {
                    // The remaining data is still too long to fit into one attribute, keep going
                    messageAttributeData = new byte[MAX_ATTR_VALUE_LENGTH];
                    bb.get(messageAttributeData, 0, MAX_ATTR_VALUE_LENGTH);
                    remainingLength -= MAX_ATTR_VALUE_LENGTH;
                } else {
                    // The remaining data fits, this will be the last chunk
                    messageAttributeData = new byte[remainingLength];
                    bb.get(messageAttributeData, 0, remainingLength);
                }
                this.attributes.add(new RADIUSAttribute(RADIUSAttribute.RADIUS_ATTR_EAP_MESSAGE,
                        (byte) (messageAttributeData.length + 2), messageAttributeData));

                // Adding the size of the data to the total RADIUS length
                this.length += (short) (messageAttributeData.length & 0xFF);
                // Adding the size of the overhead attribute type and length
                this.length += 2;
            }
        }
    }

    /**
     * Decapsulates an EAP packet from the RADIUS packet.
     *
     * @return An EAP object containing the reassembled EAP message
     * @throws DeserializationException if packet deserialization fails
     */
    public EAP decapsulateMessage() throws DeserializationException {
        EAP message = new EAP();
        ByteArrayOutputStream messageStream = new ByteArrayOutputStream();
        // Iterating through EAP-Message attributes to concatenate their value
        for (RADIUSAttribute ra : this.getAttributeList(RADIUSAttribute.RADIUS_ATTR_EAP_MESSAGE)) {
            try {
                messageStream.write(ra.getValue());
            } catch (IOException e) {
                log.error("Error while reassembling EAP message: {}", e.getMessage());
            }
        }
        // Assembling EAP object from the concatenated stream
        message = EAP.deserializer().deserialize(messageStream.toByteArray(), 0, messageStream.size());
        return message;
    }

    /**
     * Gets a list of attributes from the RADIUS packet.
     *
     * @param attrType the type field of the required attributes
     * @return List of the attributes that matches the type or an empty list if there is none
     */
    public ArrayList<RADIUSAttribute> getAttributeList(byte attrType) {
        ArrayList<RADIUSAttribute> attrList = new ArrayList<>();
        for (int i = 0; i < this.attributes.size(); i++) {
            if (this.attributes.get(i).getType() == attrType) {
                attrList.add(this.attributes.get(i));
            }
        }
        return attrList;
    }

    /**
     * Gets an attribute from the RADIUS packet.
     *
     * @param attrType the type field of the required attribute
     * @return the first attribute that matches the type or null if does not exist
     */
    public RADIUSAttribute getAttribute(byte attrType) {
        for (int i = 0; i < this.attributes.size(); i++) {
            if (this.attributes.get(i).getType() == attrType) {
                return this.attributes.get(i);
            }
        }
        return null;
    }

    /**
     * Sets an attribute in the RADIUS packet.
     *
     * @param attrType the type field of the attribute to set
     * @param value    value to be set
     * @return reference to the attribute object
     */
    public RADIUSAttribute setAttribute(byte attrType, byte[] value) {
        byte attrLength = (byte) (value.length + 2);
        RADIUSAttribute newAttribute = new RADIUSAttribute(attrType, attrLength, value);
        this.attributes.add(newAttribute);
        this.length += (short) (attrLength & 0xFF);
        return newAttribute;
    }

    /**
     * Updates an attribute in the RADIUS packet.
     *
     * @param attrType the type field of the attribute to update
     * @param value    the value to update to
     * @return reference to the attribute object
     */
    public RADIUSAttribute updateAttribute(byte attrType, byte[] value) {
        for (int i = 0; i < this.attributes.size(); i++) {
            if (this.attributes.get(i).getType() == attrType) {
                this.length -= (short) (this.attributes.get(i).getLength() & 0xFF);
                RADIUSAttribute newAttr = new RADIUSAttribute(attrType, (byte) (value.length + 2), value);
                this.attributes.set(i, newAttr);
                this.length += (short) (newAttr.getLength() & 0xFF);
                return newAttr;
            }
        }
        return null;
    }

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

            final ByteBuffer bb = ByteBuffer.wrap(data, offset, length);
            RADIUS radius = new RADIUS();
            radius.code = bb.get();
            radius.identifier = bb.get();
            radius.length = bb.getShort();
            bb.get(radius.authenticator, 0, 16);

            checkHeaderLength(length, radius.length);

            int remainingLength = radius.length - RADIUS_MIN_LENGTH;
            while (remainingLength > 0 && bb.hasRemaining()) {

                RADIUSAttribute attr = new RADIUSAttribute();
                attr.setType(bb.get());
                attr.setLength(bb.get());
                short attrLength = (short) (attr.length & 0xff);
                attr.value = new byte[attrLength - 2];
                bb.get(attr.value, 0, attrLength - 2);
                radius.attributes.add(attr);
                remainingLength -= attrLength;
            }
            return radius;
        };
    }

    @Override
    public byte[] serialize() {
        final byte[] data = new byte[this.length];
        final ByteBuffer bb = ByteBuffer.wrap(data);

        bb.put(this.code);
        bb.put(this.identifier);
        bb.putShort(this.length);
        bb.put(this.authenticator);
        for (int i = 0; i < this.attributes.size(); i++) {
            RADIUSAttribute attr = this.attributes.get(i);
            bb.put(attr.getType());
            bb.put(attr.getLength());
            bb.put(attr.getValue());
        }

        return data;
    }


    @Override
    public String toString() {
        return toStringHelper(getClass())
                .add("code", Byte.toString(code))
                .add("identifier", Byte.toString(identifier))
                .add("length", Short.toString(length))
                .add("authenticator", Arrays.toString(authenticator))
                .toString();

        // TODO: need to handle attributes
    }
}
