/*
 * 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.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Objects;

import static com.google.common.base.MoreObjects.toStringHelper;
import static org.onosproject.lisp.msg.types.LispCanonicalAddressFormatEnum.*;

/**
 * LISP Canonical Address Formatted address class.
 * <p>
 * <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       |     Rsvd2     |            Length             |
 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 * }</pre>
 */
public class LispLcafAddress extends LispAfiAddress {

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

    private final LispCanonicalAddressFormatEnum lcafType;
    private final byte reserved1;
    private final byte reserved2;
    private final byte flag;
    private final short length;

    private static final int LCAF_AFI_CODE_BYTE_LENGTH = 2;

    private static final int LENGTH_FIELD_INDEX = 7;
    public static final int COMMON_HEADER_SIZE = 8;

    /**
     * Initializes LCAF address.
     *
     * @param lcafType  LCAF type
     * @param reserved1 reserved1 field
     * @param reserved2 reserved2 field
     * @param flag      flag field
     * @param length    length field
     */
    protected LispLcafAddress(LispCanonicalAddressFormatEnum lcafType,
                              byte reserved1, byte reserved2, byte flag, short length) {
        super(AddressFamilyIdentifierEnum.LCAF);
        this.lcafType = lcafType;
        this.reserved1 = reserved1;
        this.reserved2 = reserved2;
        this.flag = flag;
        this.length = length;
    }

    /**
     * Initializes LCAF address.
     *
     * @param lcafType  LCAF type
     * @param reserved2 reserved2 field
     * @param flag      flag field
     * @param length    length field
     */
    protected LispLcafAddress(LispCanonicalAddressFormatEnum lcafType,
                              byte reserved2, byte flag, short length) {
        super(AddressFamilyIdentifierEnum.LCAF);
        this.lcafType = lcafType;
        this.reserved2 = reserved2;
        this.flag = flag;
        this.length = length;
        this.reserved1 = 0;
    }

    /**
     * Initializes LCAF address.
     *
     * @param lcafType  LCAF type
     * @param reserved2 reserved2 field
     * @param length    length field
     */
    protected LispLcafAddress(LispCanonicalAddressFormatEnum lcafType,
                              byte reserved2, short length) {
        super(AddressFamilyIdentifierEnum.LCAF);
        this.lcafType = lcafType;
        this.reserved2 = reserved2;
        this.length = length;
        this.reserved1 = 0;
        this.flag = 0;
    }

    /**
     * Initializes LCAF address.
     *
     * @param lcafType  LCAF type
     * @param reserved2 reserved2 field
     */
    protected LispLcafAddress(LispCanonicalAddressFormatEnum lcafType, byte reserved2) {
        super(AddressFamilyIdentifierEnum.LCAF);
        this.lcafType = lcafType;
        this.reserved2 = reserved2;
        this.reserved1 = 0;
        this.flag = 0;
        this.length = 0;
    }

    /**
     * Initializes LCAF address.
     *
     * @param lcafType LCAF type
     * @param length   length field
     */
    protected LispLcafAddress(LispCanonicalAddressFormatEnum lcafType, short length) {
        super(AddressFamilyIdentifierEnum.LCAF);
        this.lcafType = lcafType;
        this.reserved1 = 0;
        this.reserved2 = 0;
        this.flag = 0;
        this.length = length;
    }

    /**
     * Initializes LCAF address.
     *
     * @param lcafType LCAF type
     */
    protected LispLcafAddress(LispCanonicalAddressFormatEnum lcafType) {
        super(AddressFamilyIdentifierEnum.LCAF);
        this.lcafType = lcafType;
        this.reserved1 = 0;
        this.reserved2 = 0;
        this.flag = 0;
        this.length = 0;
    }

    /**
     * Obtains LCAF type.
     *
     * @return LCAF type
     */
    public LispCanonicalAddressFormatEnum getType() {
        return lcafType;
    }

    /**
     * Obtains LCAF reserved1 value.
     *
     * @return LCAF reserved1 value
     */
    public byte getReserved1() {
        return reserved1;
    }

    /**
     * Obtains LCAF reserved2 value.
     *
     * @return LCAF reserved2 value
     */
    public byte getReserved2() {
        return reserved2;
    }

    /**
     * Obtains LCAF flag value.
     *
     * @return LCAF flag value
     */
    public byte getFlag() {
        return flag;
    }

    /**
     * Obtains LCAF length value.
     *
     * @return LCAF length value
     */
    public short getLength() {
        return length;
    }

    /**
     * Deserializes common fields from byte buffer.
     *
     * @param byteBuf byte buffer
     * @return LispLcafAddress with filled common data fields
     */
    public static LispLcafAddress deserializeCommon(ByteBuf byteBuf) {

        // let's skip first and second two bytes ,
        // because it represents LCAF AFI code
        byteBuf.skipBytes(LCAF_AFI_CODE_BYTE_LENGTH);

        // reserved1 -> 8 bits
        byte reserved1 = (byte) byteBuf.readUnsignedByte();

        // flags -> 8 bits
        byte flag = (byte) byteBuf.readUnsignedByte();

        // LCAF type -> 8 bits
        byte lcafType = (byte) byteBuf.readUnsignedByte();

        // reserved2 -> 8bits
        byte reserved2 = (byte) byteBuf.readUnsignedByte();

        // length -> 16 bits
        short length = (short) byteBuf.readUnsignedShort();

        return new LispLcafAddress(LispCanonicalAddressFormatEnum.valueOf(lcafType),
                reserved1, reserved2, flag, length);
    }

    /**
     * Updates the header length field value based on the size of LISP header.
     *
     * @param lcafIndex the index of LCAF address, because LCAF address is
     *                  contained inside LISP control message, so to correctly
     *                  find the right LCAF length index, we need to know the
     *                  absolute lcaf index inside LISP control message byte buf
     * @param byteBuf   netty byte buffer
     */
    public static void updateLength(int lcafIndex, ByteBuf byteBuf) {
        byteBuf.setByte(lcafIndex + LENGTH_FIELD_INDEX, byteBuf.writerIndex() - COMMON_HEADER_SIZE);
    }

    /**
     * Serializes common fields to byte buffer.
     *
     * @param byteBuf byte buffer
     * @param address LISP LCAF address instance
     */
    public static void serializeCommon(ByteBuf byteBuf, LispLcafAddress address) {

        byteBuf.writeShort(AddressFamilyIdentifierEnum.LCAF.getIanaCode());
        byteBuf.writeByte(address.getReserved1());
        byteBuf.writeByte(address.getFlag());
        byteBuf.writeByte(address.getType().getLispCode());
        byteBuf.writeByte(address.getReserved2());
        byteBuf.writeShort(address.getLength());
    }

    @Override
    public int hashCode() {
        return Objects.hash(lcafType, reserved1, reserved2, flag, length);
    }

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

        if (obj instanceof LispLcafAddress) {
            final LispLcafAddress other = (LispLcafAddress) obj;
            return Objects.equals(this.lcafType, other.lcafType) &&
                    Objects.equals(this.reserved1, other.reserved1) &&
                    Objects.equals(this.reserved2, other.reserved2) &&
                    Objects.equals(this.flag, other.flag) &&
                    Objects.equals(this.length, other.length);
        }
        return false;
    }

    @Override
    public String toString() {
        return toStringHelper(this)
                .add("lcafType", lcafType)
                .add("reserved1", reserved1)
                .add("reserved2", reserved2)
                .add("flag", flag)
                .add("length", length)
                .toString();
    }

    protected static class LcafAddressBuilder<T> {

        protected byte reserved1;
        protected byte flag;
        protected byte lcafType;
        protected byte reserved2;
        protected short length;

        /**
         * Sets reserved1 value.
         *
         * @param reserved1 reserved1 value
         * @return LcafAddressBuilder object
         */
        public T withReserved1(byte reserved1) {
            this.reserved1 = reserved1;
            return (T) this;
        }

        /**
         * Sets flag.
         *
         * @param flag flag boolean
         * @return LcafAddressBuilder object
         */
        public T withFlag(byte flag) {
            this.flag = flag;
            return (T) this;
        }

        /**
         * Sets LCAF type.
         *
         * @param lcafType LCAF type
         * @return LcafAddressBuilder object
         */
        public T withLcafType(byte lcafType) {
            this.lcafType = lcafType;
            return (T) this;
        }

        /**
         * Sets reserved2 value.
         *
         * @param reserved2 reserved2 value
         * @return LcafAddressBuilder object
         */
        public T withReserved2(byte reserved2) {
            this.reserved2 = reserved2;
            return (T) this;
        }

        /**
         * Sets length value.
         *
         * @param length length value
         * @return LcafAddressBuilder object
         */
        public T withLength(short length) {
            this.length = length;
            return (T) this;
        }

        /**
         * Builds LispLcafAddress object.
         *
         * @return LispLcafAddress instance
         */
        public LispLcafAddress build() {
            return new LispLcafAddress(LispCanonicalAddressFormatEnum.valueOf(lcafType),
                    reserved1, reserved2, flag, length);
        }
    }

    /**
     * LISP LCAF reader class.
     */
    public static class LcafAddressReader implements LispAddressReader<LispLcafAddress> {

        private static final int LCAF_TYPE_FIELD_INDEX = 4;

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

            int index = byteBuf.readerIndex();

            // LCAF type -> 8 bits
            byte lcafType = (byte) byteBuf.getUnsignedByte(index + LCAF_TYPE_FIELD_INDEX);

            if (lcafType == APPLICATION_DATA.getLispCode()) {
                return new LispAppDataLcafAddress.AppDataLcafAddressReader().readFrom(byteBuf);
            }

            if (lcafType == LIST.getLispCode()) {
                return new LispListLcafAddress.ListLcafAddressReader().readFrom(byteBuf);
            }

            if (lcafType == SEGMENT.getLispCode()) {
                return new LispSegmentLcafAddress.SegmentLcafAddressReader().readFrom(byteBuf);
            }

            if (lcafType == SOURCE_DEST.getLispCode()) {
                return new LispSourceDestLcafAddress.SourceDestLcafAddressReader().readFrom(byteBuf);
            }

            if (lcafType == TRAFFIC_ENGINEERING.getLispCode()) {
                return new LispTeLcafAddress.TeLcafAddressReader().readFrom(byteBuf);
            }

            log.warn("Unsupported LCAF type, please specify a correct LCAF type");

            return null;
        }
    }

    /**
     * LISP LCAF address writer class.
     */
    public static class LcafAddressWriter implements LispAddressWriter<LispLcafAddress> {

        @Override
        public void writeTo(ByteBuf byteBuf, LispLcafAddress address) throws LispWriterException {
            switch (address.getType()) {
                case APPLICATION_DATA:
                    new LispAppDataLcafAddress.AppDataLcafAddressWriter().writeTo(byteBuf,
                            (LispAppDataLcafAddress) address);
                    break;
                case LIST:
                    new LispListLcafAddress.ListLcafAddressWriter().writeTo(byteBuf,
                            (LispListLcafAddress) address);
                    break;
                case SEGMENT:
                    new LispSegmentLcafAddress.SegmentLcafAddressWriter().writeTo(byteBuf,
                            (LispSegmentLcafAddress) address);
                    break;
                case SOURCE_DEST:
                    new LispSourceDestLcafAddress.SourceDestLcafAddressWriter().writeTo(byteBuf,
                            (LispSourceDestLcafAddress) address);
                    break;
                case TRAFFIC_ENGINEERING:
                    new LispTeLcafAddress.TeLcafAddressWriter().writeTo(byteBuf,
                            (LispTeLcafAddress) address);
                    break;
                default:
                    log.warn("Unsupported LCAF type, please specify a correct LCAF type");
                    break;
            }
        }
    }
}
