/*
 * 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.onosproject.lisp.msg.types.lcaf;

import io.netty.buffer.ByteBuf;
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.LispAddressReader;
import org.onosproject.lisp.msg.types.LispAddressWriter;
import org.onosproject.lisp.msg.types.LispAfiAddress;

import java.util.Objects;

import static com.google.common.base.MoreObjects.toStringHelper;
import static com.google.common.base.Preconditions.checkNotNull;

/**
 * Nonce locator data type LCAF address class.
 * <p>
 * Nonce locator data type is defined in draft-ietf-lisp-lcaf-22
 * https://tools.ietf.org/html/draft-ietf-lisp-lcaf-22#page-32
 *
 * <pre>
 * {@literal
 *  0                   1                   2                   3
 *  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 * |           AFI = 16387         |     Rsvd1     |     Flags     |
 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 * |   Type = 8    |     Rsvd2     |             Length            |
 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 * |   Reserved    |                  Nonce                        |
 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 * |              AFI = x          |         Address  ...          |
 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 * }</pre>
 */
public final class LispNonceLcafAddress extends LispLcafAddress {

    private final int nonce;
    private final LispAfiAddress address;

    /**
     * Initializes nonce locator data type LCAF address.
     *
     * @param nonce   nonce
     * @param address address
     */
    private LispNonceLcafAddress(int nonce, LispAfiAddress address) {
        super(LispCanonicalAddressFormatEnum.NONCE);
        this.nonce = nonce;
        this.address = address;
    }

    /**
     * Obtains nonce.
     *
     * @return nonce
     */
    public int getNonce() {
        return nonce;
    }

    /**
     * Obtains address.
     *
     * @return address
     */
    public LispAfiAddress getAddress() {
        return address;
    }

    @Override
    public int hashCode() {
        return Objects.hash(nonce, address);
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj) {
            return true;
        }

        if (obj instanceof LispNonceLcafAddress) {
            final LispNonceLcafAddress other = (LispNonceLcafAddress) obj;
            return Objects.equals(this.nonce, other.nonce) &&
                    Objects.equals(this.address, other.address);
        }
        return false;
    }

    @Override
    public String toString() {
        return toStringHelper(this)
                .add("nonce", nonce)
                .add("address", address)
                .toString();
    }

    public static final class NonceAddressBuilder
                        extends LcafAddressBuilder<NonceAddressBuilder> {
        private int nonce;
        private LispAfiAddress address;

        /**
         * Sets nonce.
         *
         * @param nonce nonce
         * @return NonceAddressBuilder object
         */
        public NonceAddressBuilder withNonce(int nonce) {
            this.nonce = nonce;
            return this;
        }

        /**
         * Sets address.
         *
         * @param address address
         * @return NonceAddressBuilder object
         */
        public NonceAddressBuilder withAddress(LispAfiAddress address) {
            this.address = address;
            return this;
        }

        /**
         * Builds LispNonceLcafAddress instance.
         *
         * @return LispNonceLcafAddress instance
         */
        @Override
        public LispNonceLcafAddress build() {

            checkNotNull(address, "Must specify an address");

            return new LispNonceLcafAddress(nonce, address);
        }
    }

    /**
     * Nonce LCAF address reader class.
     */
    public static class NonceLcafAddressReader
                        implements LispAddressReader<LispNonceLcafAddress> {

        private static final int NONCE_SHIFT_BIT = 16;
        private static final int RESERVED_SKIP_LENGTH = 1;

        @Override
        public LispNonceLcafAddress readFrom(ByteBuf byteBuf)
                                    throws LispParseError, LispReaderException {

            deserializeCommon(byteBuf);

            byteBuf.skipBytes(RESERVED_SKIP_LENGTH);

            // nonce -> 24 bits
            int nonceFirst = byteBuf.readShort() << NONCE_SHIFT_BIT;
            int nonceSecond = byteBuf.readInt();
            int nonce = nonceFirst + nonceSecond;

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

            return new NonceAddressBuilder()
                            .withNonce(nonce)
                            .withAddress(address)
                            .build();
        }
    }

    /**
     * Nonce LCAF address writer class.
     */
    public static class NonceLcafAddressWriter
                        implements LispAddressWriter<LispNonceLcafAddress> {

        private static final int UNUSED_ZERO = 0;
        private static final int NONCE_SHIFT_BIT = 16;

        @Override
        public void writeTo(ByteBuf byteBuf, LispNonceLcafAddress address)
                                                    throws LispWriterException {
            int lcafIndex = byteBuf.writerIndex();
            LispLcafAddress.serializeCommon(byteBuf, address);

            // reserved field
            byteBuf.writeByte(UNUSED_ZERO);

            // nonce field
            int nonceFirst = address.getNonce() >> NONCE_SHIFT_BIT;
            byteBuf.writeShort((short) nonceFirst);
            int nonceSecond = address.getNonce() - (nonceFirst << NONCE_SHIFT_BIT);
            byteBuf.writeInt(nonceSecond);

            // address
            AfiAddressWriter writer = new AfiAddressWriter();
            writer.writeTo(byteBuf, address.getAddress());

            LispLcafAddress.updateLength(lcafIndex, byteBuf);
        }
    }
}
