/*
 * 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.types;

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.LispAfiAddress.AfiAddressReader;

import java.util.Objects;

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

/**
 * Instance ID type LCAF address class.
 * <p>
 * Instance ID type is defined in draft-ietf-lisp-lcaf-22
 * https://tools.ietf.org/html/draft-ietf-lisp-lcaf-22#page-7
 *
 * <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 = 2    | IID mask-len  |            Length             |
 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 * |                         Instance ID                           |
 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 * |              AFI = x          |         Address  ...          |
 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 * }</pre>
 */
public final class LispSegmentLcafAddress extends LispLcafAddress {

    private final LispAfiAddress address;
    private final int instanceId;

    /**
     * Initializes segment type LCAF address.
     *
     * @param idMaskLength Id mask length
     * @param instanceId   instance id
     * @param address      address
     */
    private LispSegmentLcafAddress(byte idMaskLength, int instanceId, LispAfiAddress address) {
        super(LispCanonicalAddressFormatEnum.SEGMENT, idMaskLength);
        this.address = address;
        this.instanceId = instanceId;
    }

    /**
     * Initializes segment type LCAF address.
     *
     * @param reserved1    reserved1
     * @param idMaskLength ID mask length
     * @param flag         flag
     * @param length       length
     * @param instanceId   instance id
     * @param address      address
     */
    private LispSegmentLcafAddress(byte reserved1, byte idMaskLength, byte flag, short length,
                                   int instanceId, LispAfiAddress address) {
        super(LispCanonicalAddressFormatEnum.SEGMENT, reserved1, idMaskLength, flag, length);
        this.address = address;
        this.instanceId = instanceId;
    }

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

    /**
     * Obtains instance id.
     *
     * @return instance id
     */
    public int getInstanceId() {
        return instanceId;
    }

    /**
     * Obtains id mask length.
     *
     * @return id mask length
     */
    public byte getIdMaskLength() {
        return getReserved2();
    }

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

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

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

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

    public static final class SegmentAddressBuilder
                              extends LcafAddressBuilder<SegmentAddressBuilder> {
        private byte idMaskLength;
        private LispAfiAddress address;
        private int instanceId;

        /**
         * Sets identifier mask length.
         *
         * @param idMaskLength identifier mask length
         * @return SegmentAddressBuilder object
         */
        public SegmentAddressBuilder withIdMaskLength(byte idMaskLength) {
            this.idMaskLength = idMaskLength;
            return this;
        }

        /**
         * Sets instance identifer.
         *
         * @param instanceId instance identifier
         * @return SegmentAddressBuilder object
         */
        public SegmentAddressBuilder withInstanceId(int instanceId) {
            this.instanceId = instanceId;
            return this;
        }

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

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

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

            return new LispSegmentLcafAddress(reserved1, idMaskLength, flag,
                                              length, instanceId, address);
        }
    }

    /**
     * Segment LCAF address reader class.
     */
    public static class SegmentLcafAddressReader
            implements LispAddressReader<LispSegmentLcafAddress> {

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

            LispLcafAddress lcafAddress = LispLcafAddress.deserializeCommon(byteBuf);

            byte idMaskLength = lcafAddress.getReserved2();

            int instanceId = (int) byteBuf.readUnsignedInt();
            LispAfiAddress address = new AfiAddressReader().readFrom(byteBuf);

            return new SegmentAddressBuilder()
                    .withReserved1(lcafAddress.getReserved1())
                    .withFlag(lcafAddress.getFlag())
                    .withLength(lcafAddress.getLength())
                    .withIdMaskLength(idMaskLength)
                    .withInstanceId(instanceId)
                    .withAddress(address)
                    .build();
        }
    }

    /**
     * Segment LCAF address writer class.
     */
    public static class SegmentLcafAddressWriter
            implements LispAddressWriter<LispSegmentLcafAddress> {

        @Override
        public void writeTo(ByteBuf byteBuf, LispSegmentLcafAddress address)
                throws LispWriterException {

            int lcafIndex = byteBuf.writerIndex();
            LispLcafAddress.serializeCommon(byteBuf, address);

            byteBuf.writeInt(address.getInstanceId());

            new LispAfiAddress.AfiAddressWriter().writeTo(byteBuf, address.getAddress());

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