/*
 * 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 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
            LispAfiAddress.AfiAddressWriter writer = new LispAfiAddress.AfiAddressWriter();
            writer.writeTo(byteBuf, record.rtrRlocAddress);
        }
    }
}
