/*
 * Copyright 2016-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.onosproject.lisp.msg.protocols;

import io.netty.buffer.ByteBuf;
import org.onlab.util.ByteOperator;
import org.onlab.util.ImmutableByteSequence;
import org.onosproject.lisp.msg.exceptions.LispParseError;
import org.onosproject.lisp.msg.exceptions.LispReaderException;
import org.onosproject.lisp.msg.exceptions.LispWriterException;
import org.onosproject.lisp.msg.types.LispAfiAddress;
import org.onosproject.lisp.msg.types.LispAfiAddress.AfiAddressWriter;

import java.util.Arrays;

/**
 * A class that contains a set of helper methods for LISP info request and reply.
 */
public class DefaultLispInfo implements LispInfo {

    protected final boolean infoReply;
    protected final long nonce;
    protected final short keyId;
    protected final short authDataLength;
    protected final byte[] authenticationData;
    protected final int ttl;
    protected final byte maskLength;
    protected final LispAfiAddress eidPrefix;

    private static final int INFO_REPLY_INDEX = 3;
    private static final int RESERVED_SKIP_LENGTH_1 = 3;
    private static final int RESERVED_SKIP_LENGTH_2 = 1;

    private static final int INFO_REQUEST_SHIFT_BIT = 4;

    private static final int ENABLE_BIT = 1;
    private static final int DISABLE_BIT = 0;

    private static final int UNUSED_ZERO = 0;

    /**
     * A private constructor that protects object instantiation from external.
     *
     * @param infoReply          info reply flag
     * @param nonce              nonce
     * @param keyId              key identifier
     * @param authDataLength     authentication data length
     * @param authenticationData authentication data
     * @param ttl                Time-To-Live value
     * @param maskLength         EID prefix mask length
     * @param eidPrefix          EID prefix
     */
    protected DefaultLispInfo(boolean infoReply, long nonce, short keyId, short authDataLength,
                              byte[] authenticationData, int ttl, byte maskLength,
                              LispAfiAddress eidPrefix) {
        this.infoReply = infoReply;
        this.nonce = nonce;
        this.keyId = keyId;
        this.authDataLength = authDataLength;
        this.authenticationData = authenticationData;
        this.ttl = ttl;
        this.maskLength = maskLength;
        this.eidPrefix = eidPrefix;
    }

    @Override
    public LispType getType() {
        return LispType.LISP_INFO;
    }

    @Override
    public void writeTo(ByteBuf byteBuf) {
        // TODO: serialize LispMapRegister message
    }

    @Override
    public Builder createBuilder() {
        return new DefaultLispInfoRequest.DefaultInfoRequestBuilder();
    }

    @Override
    public boolean hasInfoReply() {
        return infoReply;
    }

    @Override
    public long getNonce() {
        return nonce;
    }

    @Override
    public short getKeyId() {
        return keyId;
    }

    @Override
    public short getAuthDataLength() {
        return authDataLength;
    }

    @Override
    public byte[] getAuthenticationData() {
        if (authenticationData != null && authenticationData.length != 0) {
            return ImmutableByteSequence.copyFrom(authenticationData).asArray();
        } else {
            return new byte[0];
        }
    }

    @Override
    public int getTtl() {
        return ttl;
    }

    @Override
    public byte getMaskLength() {
        return maskLength;
    }

    @Override
    public LispAfiAddress getPrefix() {
        return eidPrefix;
    }

    public static LispInfo deserialize(ByteBuf byteBuf) throws LispParseError, LispReaderException {

        if (byteBuf.readerIndex() != 0) {
            return null;
        }

        // infoReply -> 1 bit
        boolean infoReplyFlag = ByteOperator.getBit(byteBuf.readByte(), INFO_REPLY_INDEX);

        // let's skip the reserved field
        byteBuf.skipBytes(RESERVED_SKIP_LENGTH_1);

        // nonce -> 64 bits
        long nonce = byteBuf.readLong();

        // keyId -> 16 bits
        short keyId = byteBuf.readShort();

        // authenticationDataLength -> 16 bits
        short authLength = byteBuf.readShort();

        // authenticationData -> depends on the authenticationDataLength
        byte[] authData = new byte[authLength];
        byteBuf.readBytes(authData);

        // ttl -> 32 bits
        int ttl = byteBuf.readInt();

        // let's skip the reserved field
        byteBuf.skipBytes(RESERVED_SKIP_LENGTH_2);

        // mask length -> 8 bits
        short maskLength = byteBuf.readUnsignedByte();

        LispAfiAddress prefix = new LispAfiAddress.AfiAddressReader().readFrom(byteBuf);

        return new DefaultLispInfo(infoReplyFlag, nonce, keyId, authLength,
                authData, ttl, (byte) maskLength, prefix);
    }

    public static void serialize(ByteBuf byteBuf, LispInfo message) throws LispWriterException {

        // specify LISP message type
        byte msgType = (byte) (LispType.LISP_INFO.getTypeCode() << INFO_REQUEST_SHIFT_BIT);

        // info reply flag
        byte infoReply = DISABLE_BIT;
        if (message.hasInfoReply()) {
            infoReply = (byte) (ENABLE_BIT << INFO_REPLY_INDEX);
        }

        byteBuf.writeByte(msgType + infoReply);

        // fill zero into reserved filed
        byteBuf.writeByte((short) UNUSED_ZERO);
        byteBuf.writeByte((short) UNUSED_ZERO);
        byteBuf.writeByte((short) UNUSED_ZERO);

        // nonce
        byteBuf.writeLong(message.getNonce());

        // keyId
        byteBuf.writeShort(message.getKeyId());

        // authentication data length in octet
        byteBuf.writeShort(message.getAuthDataLength());

        // authentication data
        byte[] data = message.getAuthenticationData();
        byte[] clone;
        if (data != null) {
            clone = data.clone();
            Arrays.fill(clone, (byte) UNUSED_ZERO);
        }

        byteBuf.writeBytes(data);

        // TODO: need to implement MAC authentication mechanism

        /// TTL
        byteBuf.writeInt(message.getTtl());

        // fill zero into reserved filed
        byteBuf.writeByte((short) UNUSED_ZERO);

        // mask length
        byteBuf.writeByte(message.getMaskLength());

        // EID prefix AFI with EID prefix
        AfiAddressWriter afiAddressWriter = new AfiAddressWriter();
        afiAddressWriter.writeTo(byteBuf, message.getPrefix());
    }
}
