/*
 * 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 com.google.common.base.Objects;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import org.onosproject.lisp.msg.types.LispAfiAddress;
import org.onosproject.lisp.msg.authentication.LispAuthenticationFactory;
import org.onosproject.lisp.msg.authentication.LispAuthenticationKeyEnum;
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.LispLcafAddress.LcafAddressReader;
import org.onosproject.lisp.msg.types.LispLcafAddress.LcafAddressWriter;
import org.onosproject.lisp.msg.types.LispNatLcafAddress;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Arrays;

import static com.google.common.base.MoreObjects.toStringHelper;
import static org.onosproject.lisp.msg.authentication.LispAuthenticationKeyEnum.valueOf;

/**
 * Default LISP info reply message class.
 */
public final class DefaultLispInfoReply extends DefaultLispInfo implements LispInfoReply {

    private static final Logger log = LoggerFactory.getLogger(DefaultLispInfoReply.class);

    private final LispNatLcafAddress natLcafAddress;

    static final InfoReplyWriter WRITER;

    static {
        WRITER = new InfoReplyWriter();
    }

    /**
     * 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 authData       authentication data
     * @param ttl            Time-To-Live value
     * @param maskLength     EID prefix mask length
     * @param eidPrefix      EID prefix
     * @param natLcafAddress NAT LCAF address
     */
    protected DefaultLispInfoReply(boolean infoReply, long nonce, short keyId, short authDataLength,
                                   byte[] authData, int ttl, byte maskLength,
                                   LispAfiAddress eidPrefix, LispNatLcafAddress natLcafAddress) {
        super(infoReply, nonce, keyId, authDataLength, authData, ttl, maskLength, eidPrefix);
        this.natLcafAddress = natLcafAddress;
    }

    @Override
    public LispNatLcafAddress getNatLcafAddress() {
        return natLcafAddress;
    }

    @Override
    public void writeTo(ByteBuf byteBuf) throws LispWriterException {
        WRITER.writeTo(byteBuf, this);
    }

    @Override
    public String toString() {
        return toStringHelper(this)
                .add("type", getType())
                .add("nonce", nonce)
                .add("keyId", keyId)
                .add("authentication data length", authDataLength)
                .add("authentication data", authData)
                .add("TTL", ttl)
                .add("EID mask length", maskLength)
                .add("EID prefix", eidPrefix)
                .add("NAT LCAF address", natLcafAddress).toString();
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) {
            return true;
        }
        if (o == null || getClass() != o.getClass()) {
            return false;
        }

        DefaultLispInfoReply that = (DefaultLispInfoReply) o;
        return Objects.equal(nonce, that.nonce) &&
                Objects.equal(keyId, that.keyId) &&
                Objects.equal(authDataLength, that.authDataLength) &&
                Arrays.equals(authData, that.authData) &&
                Objects.equal(ttl, that.ttl) &&
                Objects.equal(maskLength, that.maskLength) &&
                Objects.equal(eidPrefix, that.eidPrefix) &&
                Objects.equal(natLcafAddress, that.natLcafAddress);
    }

    @Override
    public int hashCode() {
        return Objects.hashCode(nonce, keyId, authDataLength, ttl, maskLength,
                eidPrefix, natLcafAddress) + Arrays.hashCode(authData);
    }

    public static final class DefaultInfoReplyBuilder implements InfoReplyBuilder {

        private boolean infoReply;
        private long nonce;
        private short keyId;
        private short authDataLength;
        private byte[] authData;
        private String authKey;
        private int ttl;
        private byte maskLength;
        private LispAfiAddress eidPrefix;
        private LispNatLcafAddress natLcafAddress;

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


        @Override
        public InfoReplyBuilder withIsInfoReply(boolean infoReply) {
            this.infoReply = infoReply;
            return this;
        }

        @Override
        public InfoReplyBuilder withNonce(long nonce) {
            this.nonce = nonce;
            return this;
        }

        @Override
        public InfoReplyBuilder withAuthDataLength(short authDataLength) {
            this.authDataLength = authDataLength;
            return this;
        }

        @Override
        public InfoReplyBuilder withKeyId(short keyId) {
            this.keyId = keyId;
            return this;
        }

        @Override
        public InfoReplyBuilder withAuthData(byte[] authenticationData) {
            if (authenticationData != null) {
                this.authData = authenticationData;
            }
            return this;
        }

        @Override
        public InfoReplyBuilder withAuthKey(String key) {
            this.authKey = key;
            return this;
        }

        @Override
        public InfoReplyBuilder withTtl(int ttl) {
            this.ttl = ttl;
            return this;
        }

        @Override
        public InfoReplyBuilder withMaskLength(byte maskLength) {
            this.maskLength = maskLength;
            return this;
        }

        @Override
        public InfoReplyBuilder withEidPrefix(LispAfiAddress eidPrefix) {
            this.eidPrefix = eidPrefix;
            return this;
        }


        @Override
        public InfoReplyBuilder withNatLcafAddress(LispNatLcafAddress natLcafAddress) {
            this.natLcafAddress = natLcafAddress;
            return this;
        }

        @Override
        public LispInfoReply build() {

            // if authentication data is not specified, we will calculate it
            if (authData == null) {
                LispAuthenticationFactory factory = LispAuthenticationFactory.getInstance();

                authDataLength = LispAuthenticationKeyEnum.valueOf(keyId).getHashLength();
                byte[] tmpAuthData = new byte[authDataLength];
                Arrays.fill(tmpAuthData, (byte) 0);
                authData = tmpAuthData;

                ByteBuf byteBuf = Unpooled.buffer();
                try {
                    new DefaultLispInfoReply(infoReply, nonce, keyId, authDataLength,
                            authData, ttl, maskLength, eidPrefix, natLcafAddress).writeTo(byteBuf);
                } catch (LispWriterException e) {
                    log.warn("Failed to serialize info reply", e);
                }

                byte[] bytes = new byte[byteBuf.readableBytes()];
                byteBuf.readBytes(bytes);

                if (authKey == null) {
                    log.warn("Must specify authentication key");
                }

                authData = factory.createAuthenticationData(valueOf(keyId), authKey, bytes);
            }

            return new DefaultLispInfoReply(infoReply, nonce, keyId, authDataLength,
                    authData, ttl, maskLength, eidPrefix, natLcafAddress);
        }
    }

    /**
     * A LISP message reader for InfoReply message.
     */
    public static final class InfoReplyReader implements LispMessageReader<LispInfoReply> {

        @Override
        public LispInfoReply readFrom(ByteBuf byteBuf) throws LispParseError, LispReaderException {
            LispInfo lispInfo = deserialize(byteBuf);

            LispNatLcafAddress natLcafAddress = (LispNatLcafAddress)
                    new LcafAddressReader().readFrom(byteBuf);

            return new DefaultInfoReplyBuilder()
                    .withIsInfoReply(lispInfo.isInfoReply())
                    .withNonce(lispInfo.getNonce())
                    .withKeyId(lispInfo.getKeyId())
                    .withAuthDataLength(lispInfo.getAuthDataLength())
                    .withAuthData(lispInfo.getAuthData())
                    .withTtl(lispInfo.getTtl())
                    .withMaskLength(lispInfo.getMaskLength())
                    .withEidPrefix(lispInfo.getPrefix())
                    .withNatLcafAddress(natLcafAddress).build();
        }
    }

    public static final class InfoReplyWriter implements LispMessageWriter<LispInfoReply> {

        @Override
        public void writeTo(ByteBuf byteBuf, LispInfoReply message) throws LispWriterException {
            serialize(byteBuf, message);

            new LcafAddressWriter().writeTo(byteBuf, message.getNatLcafAddress());
        }
    }
}
