/*
 * 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.onlab.util.ByteOperator;
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 org.onosproject.lisp.msg.types.LispAfiAddress.AfiAddressWriter;

import java.util.Objects;

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

/**
 * Traffic Engineering record class.
 */
public class LispTeRecord {

    private final boolean lookup;
    private final boolean rlocProbe;
    private final boolean strict;
    private final LispAfiAddress rtrRlocAddress;

    /**
     * Initializes TE record.
     *
     * @param lookup     lookup bit
     * @param rlocProbe  rloc probe bit
     * @param strict     strict bit
     * @param rtrAddress RTR address
     */
    public LispTeRecord(boolean lookup, boolean rlocProbe,
                        boolean strict, LispAfiAddress rtrAddress) {
        this.lookup = lookup;
        this.rlocProbe = rlocProbe;
        this.strict = strict;
        this.rtrRlocAddress = rtrAddress;
    }

    /**
     * Obtains lookup bit flag.
     *
     * @return lookup bit flag
     */
    public boolean isLookup() {
        return lookup;
    }

    /**
     * Obtains RLOC probe bit flag.
     *
     * @return RLOC probe bit flag
     */
    public boolean isRlocProbe() {
        return rlocProbe;
    }

    /**
     * Obtains strict bit flag.
     *
     * @return strict bit flag
     */
    public boolean isStrict() {
        return strict;
    }

    /**
     * Obtains Re-encapsulated RLOC address.
     *
     * @return Re-encapsulated RLOC address
     */
    public LispAfiAddress getRtrRlocAddress() {
        return rtrRlocAddress;
    }

    @Override
    public int hashCode() {
        return Objects.hash(lookup, rlocProbe, strict, rtrRlocAddress);
    }

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

        if (obj instanceof LispTeRecord) {
            final LispTeRecord other = (LispTeRecord) obj;
            return Objects.equals(this.lookup, other.lookup) &&
                    Objects.equals(this.rlocProbe, other.rlocProbe) &&
                    Objects.equals(this.strict, other.strict) &&
                    Objects.equals(this.rtrRlocAddress, other.rtrRlocAddress);
        }
        return false;
    }

    @Override
    public String toString() {
        return toStringHelper(this)
                .add("Lookup bit", lookup)
                .add("RLOC probe bit", rlocProbe)
                .add("strict bit", strict)
                .add("RTR address", rtrRlocAddress)
                .toString();
    }

    public static final class TeRecordBuilder {
        private boolean lookup;
        private boolean rlocProbe;
        private boolean strict;
        private LispAfiAddress rtrRlocAddress;

        /**
         * Sets lookup flag.
         *
         * @param lookup lookup flag
         * @return TeRecordBuilder object
         */
        public TeRecordBuilder withIsLookup(boolean lookup) {
            this.lookup = lookup;
            return this;
        }

        /**
         * Sets RLOC probe flag.
         *
         * @param rlocProbe RLOC probe flag
         * @return TeRecordBuilder object
         */
        public TeRecordBuilder withIsRlocProbe(boolean rlocProbe) {
            this.rlocProbe = rlocProbe;
            return this;
        }

        /**
         * Sets strict flag.
         *
         * @param strict strict flag
         * @return TeRecordBuilder object
         */
        public TeRecordBuilder withIsStrict(boolean strict) {
            this.strict = strict;
            return this;
        }

        /**
         * Sets RTR RLOC address.
         *
         * @param rtrRlocAddress RTR RLOC address
         * @return TeRecordBuilder object
         */
        public TeRecordBuilder withRtrRlocAddress(LispAfiAddress rtrRlocAddress) {
            this.rtrRlocAddress = rtrRlocAddress;
            return this;
        }

        /**
         * Builds TeRecord instance.
         *
         * @return TeRcord instance
         */
        public LispTeRecord build() {

            return new LispTeRecord(lookup, rlocProbe, strict, rtrRlocAddress);
        }
    }

    /**
     * Traffic Engineering record reader class.
     */
    public static class TeRecordReader implements LispAddressReader<LispTeRecord> {

        private static final int RESERVED_SKIP_LENGTH = 1;

        private static final int STRICT_INDEX = 1;
        private static final int RLOC_PROBE_INDEX = 2;
        private static final int LOOKUP_INDEX = 3;

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

            // let's skip reserved 3
            byteBuf.skipBytes(RESERVED_SKIP_LENGTH);

            byte flags = byteBuf.readByte();

            // lookup -> 1 bit
            boolean lookup = ByteOperator.getBit(flags, LOOKUP_INDEX);

            // rlocProbe -> 1 bit
            boolean rlocProbe = ByteOperator.getBit(flags, RLOC_PROBE_INDEX);

            // strict -> 1 bit
            boolean strict = ByteOperator.getBit(flags, STRICT_INDEX);

            AfiAddressReader reader = new AfiAddressReader();

            LispAfiAddress rtrAddress = reader.readFrom(byteBuf);

            return new LispTeRecord(lookup, rlocProbe, strict, rtrAddress);
        }
    }

    /**
     * Traffic Engineering record writer class.
     */
    public static class TeRecordWriter implements LispAddressWriter<LispTeRecord> {

        private static final int LOOKUP_FLAG_SHIFT_BIT = 3;
        private static final int RLOC_PROBE_FLAG_SHIFT_BIT = 2;
        private static final int STRICT_FLAG_SHIFT_BIT = 1;

        private static final int ENABLE_BIT = 1;
        private static final int DISABLE_BIT = 0;

        private static final int UNUSED_ZERO = 0;

        @Override
        public void writeTo(ByteBuf byteBuf, LispTeRecord record)
                                                    throws LispWriterException {

            byteBuf.writeByte(UNUSED_ZERO);

            // lookup flag
            byte lookup = DISABLE_BIT;
            if (record.isLookup()) {
                lookup = (byte) (ENABLE_BIT << LOOKUP_FLAG_SHIFT_BIT);
            }

            // RLOC probe flag
            byte rlocProbe = DISABLE_BIT;
            if (record.isRlocProbe()) {
                rlocProbe = (byte) (ENABLE_BIT << RLOC_PROBE_FLAG_SHIFT_BIT);
            }

            // strict flag
            byte strict = DISABLE_BIT;
            if (record.isStrict()) {
                strict = (byte) (ENABLE_BIT << STRICT_FLAG_SHIFT_BIT);
            }

            byteBuf.writeByte((byte) (lookup + rlocProbe + strict));

            // RTR RLOC address
            AfiAddressWriter writer = new AfiAddressWriter();
            writer.writeTo(byteBuf, record.rtrRlocAddress);
        }
    }
}
