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

import com.google.common.base.Objects;
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;
import org.onosproject.lisp.msg.types.LispAfiAddress.AfiAddressReader;
import org.onosproject.lisp.msg.types.LispAfiAddress.AfiAddressWriter;

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

/**
 * Default implementation of LispLocatorRecord.
 */
public final class DefaultLispLocatorRecord implements LispLocatorRecord {

    private final byte priority;
    private final byte weight;
    private final byte multicastPriority;
    private final byte multicastWeight;
    private final boolean localLocator;
    private final boolean rlocProbed;
    private final boolean routed;
    private final LispAfiAddress locatorAfi;

    static final LocatorRecordWriter WRITER;
    static {
        WRITER = new LocatorRecordWriter();
    }

    /**
     * A private constructor that protects object instantiation from external.
     *
     * @param priority          uni-cast priority
     * @param weight            uni-cast weight
     * @param multicastPriority multi-cast priority
     * @param multicastWeight   multi-cast weight
     * @param localLocator      local locator flag
     * @param rlocProbed        RLOC probed flag
     * @param routed            routed flag
     * @param locatorAfi        locator AFI
     */
    private DefaultLispLocatorRecord(byte priority, byte weight, byte multicastPriority,
                                     byte multicastWeight, boolean localLocator, boolean rlocProbed,
                                     boolean routed, LispAfiAddress locatorAfi) {
        this.priority = priority;
        this.weight = weight;
        this.multicastPriority = multicastPriority;
        this.multicastWeight = multicastWeight;
        this.localLocator = localLocator;
        this.rlocProbed = rlocProbed;
        this.routed = routed;
        this.locatorAfi = locatorAfi;
    }

    @Override
    public byte getPriority() {
        return priority;
    }

    @Override
    public byte getWeight() {
        return weight;
    }

    @Override
    public byte getMulticastPriority() {
        return multicastPriority;
    }

    @Override
    public byte getMulticastWeight() {
        return multicastWeight;
    }

    @Override
    public boolean isLocalLocator() {
        return localLocator;
    }

    @Override
    public boolean isRlocProbed() {
        return rlocProbed;
    }

    @Override
    public boolean isRouted() {
        return routed;
    }

    @Override
    public LispAfiAddress getLocatorAfi() {
        return locatorAfi;
    }

    @Override
    public void writeTo(ByteBuf byteBuf) throws LispWriterException {
        WRITER.writeTo(byteBuf, this);
    }

    @Override
    public String toString() {
        return toStringHelper(this)
                .add("priority", priority)
                .add("weight", weight)
                .add("multi-cast priority", multicastPriority)
                .add("multi-cast weight", multicastWeight)
                .add("local locator", localLocator)
                .add("RLOC probed", rlocProbed)
                .add("routed", routed)
                .add("locator AFI", locatorAfi).toString();
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) {
            return true;
        }
        if (o == null || getClass() != o.getClass()) {
            return false;
        }
        DefaultLispLocatorRecord that = (DefaultLispLocatorRecord) o;
        return Objects.equal(priority, that.priority) &&
                Objects.equal(weight, that.weight) &&
                Objects.equal(multicastPriority, that.multicastPriority) &&
                Objects.equal(multicastWeight, that.multicastWeight) &&
                Objects.equal(localLocator, that.localLocator) &&
                Objects.equal(rlocProbed, that.rlocProbed) &&
                Objects.equal(routed, that.routed) &&
                Objects.equal(locatorAfi, that.locatorAfi);
    }

    @Override
    public int hashCode() {
        return Objects.hashCode(priority, weight, multicastPriority,
                multicastWeight, localLocator, rlocProbed, routed, locatorAfi);
    }

    public static final class DefaultLocatorRecordBuilder implements LocatorRecordBuilder {

        private byte priority;
        private byte weight;
        private byte multicastPriority;
        private byte multicastWeight;
        private boolean localLocator;
        private boolean rlocProbed;
        private boolean routed;
        private LispAfiAddress locatorAfi;

        @Override
        public LocatorRecordBuilder withPriority(byte priority) {
            this.priority = priority;
            return this;
        }

        @Override
        public LocatorRecordBuilder withWeight(byte weight) {
            this.weight = weight;
            return this;
        }

        @Override
        public LocatorRecordBuilder withMulticastPriority(byte priority) {
            this.multicastPriority = priority;
            return this;
        }

        @Override
        public LocatorRecordBuilder withMulticastWeight(byte weight) {
            this.multicastWeight = weight;
            return this;
        }

        @Override
        public LocatorRecordBuilder withLocalLocator(boolean localLocator) {
            this.localLocator = localLocator;
            return this;
        }

        @Override
        public LocatorRecordBuilder withRlocProbed(boolean rlocProbed) {
            this.rlocProbed = rlocProbed;
            return this;
        }

        @Override
        public LocatorRecordBuilder withRouted(boolean routed) {
            this.routed = routed;
            return this;
        }

        @Override
        public LocatorRecordBuilder withLocatorAfi(LispAfiAddress locatorAfi) {
            this.locatorAfi = locatorAfi;
            return this;
        }

        @Override
        public LispLocatorRecord build() {

            checkNotNull(locatorAfi, "Must specify a locator address");

            return new DefaultLispLocatorRecord(priority, weight, multicastPriority,
                    multicastWeight, localLocator, rlocProbed, routed, locatorAfi);
        }
    }

    /**
     * A LISP message reader for LocatorRecord portion.
     */
    public static final class LocatorRecordReader implements LispMessageReader<LispLocatorRecord> {

        private static final int SKIP_UNUSED_FLAG_LENGTH = 1;
        private static final int LOCAL_LOCATOR_INDEX = 2;
        private static final int RLOC_PROBED_INDEX = 1;
        private static final int ROUTED_INDEX = 0;

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

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

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

            // multi-cast priority -> 8 bits
            byte multicastPriority = (byte) byteBuf.readUnsignedByte();

            // multi-cast weight -> 8 bits
            byte multicastWeight = (byte) byteBuf.readUnsignedByte();

            // let's skip unused flags
            byteBuf.skipBytes(SKIP_UNUSED_FLAG_LENGTH);

            byte flags = byteBuf.readByte();

            // local locator flag -> 1 bit
            boolean localLocator = ByteOperator.getBit(flags, LOCAL_LOCATOR_INDEX);

            // rloc probe flag -> 1 bit
            boolean rlocProbed = ByteOperator.getBit(flags, RLOC_PROBED_INDEX);

            // routed flag -> 1 bit
            boolean routed = ByteOperator.getBit(flags, ROUTED_INDEX);

            LispAfiAddress address = new AfiAddressReader().readFrom(byteBuf);

            return new DefaultLocatorRecordBuilder()
                        .withPriority(priority)
                        .withWeight(weight)
                        .withMulticastPriority(multicastPriority)
                        .withMulticastWeight(multicastWeight)
                        .withLocalLocator(localLocator)
                        .withRlocProbed(rlocProbed)
                        .withRouted(routed)
                        .withLocatorAfi(address)
                        .build();
        }
    }

    /**
     * A LISP message writer for LocatorRecord portion.
     */
    public static final class LocatorRecordWriter implements LispMessageWriter<LispLocatorRecord> {

        private static final int LOCAL_LOCATOR_SHIFT_BIT = 2;
        private static final int PROBED_SHIFT_BIT = 1;

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

        @Override
        public void writeTo(ByteBuf byteBuf, LispLocatorRecord message) throws LispWriterException {

            // priority
            byteBuf.writeByte(message.getPriority());

            // weight
            byteBuf.writeByte(message.getWeight());

            // multicast priority
            byteBuf.writeByte(message.getMulticastPriority());

            // multicast weight
            byteBuf.writeByte(message.getMulticastWeight());

            // unused flags
            byteBuf.writeByte((short) 0);

            // localLocator flag
            short localLocator = DISABLE_BIT;
            if (message.isLocalLocator()) {
                localLocator = (byte) (ENABLE_BIT << LOCAL_LOCATOR_SHIFT_BIT);
            }

            // rlocProbed flag
            short probed = DISABLE_BIT;
            if (message.isRlocProbed()) {
                probed = (byte) (ENABLE_BIT << PROBED_SHIFT_BIT);
            }

            // routed flag
            short routed = DISABLE_BIT;
            if (message.isRouted()) {
                routed = (byte) ENABLE_BIT;
            }

            byteBuf.writeByte((byte) (localLocator + probed + routed));

            // EID prefix AFI with EID prefix
            AfiAddressWriter afiAddressWriter = new AfiAddressWriter();
            afiAddressWriter.writeTo(byteBuf, message.getLocatorAfi());
        }
    }
}
