/*
 * 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 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-13
 * https://tools.ietf.org/html/draft-ietf-lisp-lcaf-13#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  |             4 + n             |
 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 * |                         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 LispAfiAddress.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 {

            LispLcafAddress.serializeCommon(byteBuf, address);

            byteBuf.writeInt(address.getInstanceId());

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