/*
 * 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 com.google.common.collect.ImmutableList;
import com.google.common.collect.Lists;
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.protocols.DefaultLispMapRecord.MapRecordReader;
import org.onosproject.lisp.msg.protocols.DefaultLispMapRecord.MapRecordWriter;

import java.util.List;

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

/**
 * Default LISP map reply message class.
 */
public final class DefaultLispMapReply extends AbstractLispMessage
        implements LispMapReply {

    private final long nonce;
    private final boolean probe;
    private final boolean etr;
    private final boolean security;
    private final List<LispMapRecord> mapRecords;

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

    /**
     * A private constructor that protects object instantiation from external.
     *
     * @param nonce       nonce
     * @param probe       probe flag
     * @param etr         etr flag
     * @param security    security flag
     */
    private DefaultLispMapReply(long nonce, boolean probe, boolean etr,
                                boolean security, List<LispMapRecord> mapRecords) {
        this.nonce = nonce;
        this.probe = probe;
        this.etr = etr;
        this.security = security;
        this.mapRecords = mapRecords;
    }

    @Override
    public LispType getType() {
        return LispType.LISP_MAP_REPLY;
    }

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

    @Override
    public Builder createBuilder() {
        return new DefaultReplyBuilder();
    }

    @Override
    public boolean isProbe() {
        return probe;
    }

    @Override
    public boolean isEtr() {
        return etr;
    }

    @Override
    public boolean isSecurity() {
        return security;
    }

    @Override
    public int getRecordCount() {
        return mapRecords.size();
    }

    @Override
    public long getNonce() {
        return nonce;
    }

    @Override
    public List<LispMapRecord> getMapRecords() {
        return ImmutableList.copyOf(mapRecords);
    }

    @Override
    public String toString() {
        return toStringHelper(this)
                .add("type", getType())
                .add("nonce", nonce)
                .add("probe", probe)
                .add("etr", etr)
                .add("security", security)
                .add("map records", mapRecords).toString();
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) {
            return true;
        }
        if (o == null || getClass() != o.getClass()) {
            return false;
        }
        DefaultLispMapReply that = (DefaultLispMapReply) o;
        return Objects.equal(nonce, that.nonce) &&
                Objects.equal(probe, that.probe) &&
                Objects.equal(etr, that.etr) &&
                Objects.equal(security, that.security) &&
                Objects.equal(mapRecords, that.mapRecords);
    }

    @Override
    public int hashCode() {
        return Objects.hashCode(nonce, probe, etr, security, mapRecords);
    }

    public static final class DefaultReplyBuilder implements ReplyBuilder {

        private long nonce;
        private boolean probe;
        private boolean etr;
        private boolean security;
        private List<LispMapRecord> mapRecords = Lists.newArrayList();

        @Override
        public LispType getType() {
            return LispType.LISP_MAP_REPLY;
        }

        @Override
        public ReplyBuilder withIsProbe(boolean probe) {
            this.probe = probe;
            return this;
        }

        @Override
        public ReplyBuilder withIsEtr(boolean etr) {
            this.etr = etr;
            return this;
        }

        @Override
        public ReplyBuilder withIsSecurity(boolean security) {
            this.security = security;
            return this;
        }

        @Override
        public ReplyBuilder withNonce(long nonce) {
            this.nonce = nonce;
            return this;
        }

        @Override
        public ReplyBuilder withMapRecords(List<LispMapRecord> mapRecords) {
            if (this.mapRecords != null) {
                this.mapRecords = ImmutableList.copyOf(mapRecords);
            }
            return this;
        }

        @Override
        public LispMapReply build() {
            return new DefaultLispMapReply(nonce, probe, etr, security, mapRecords);
        }
    }

    /**
     * A LISP message reader for MapReply message.
     */
    public static final class ReplyReader implements LispMessageReader<LispMapReply> {

        private static final int PROBE_INDEX = 3;
        private static final int ETR_INDEX = 2;
        private static final int SECURITY_INDEX = 1;
        private static final int RESERVED_SKIP_LENGTH = 2;

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

            if (byteBuf.readerIndex() != 0) {
                return null;
            }

            byte typeWithFlags = byteBuf.readByte();

            // probe -> 1 bit
            boolean probe = ByteOperator.getBit(typeWithFlags, PROBE_INDEX);

            // etr -> 1bit
            boolean etr = ByteOperator.getBit(typeWithFlags, ETR_INDEX);

            // security -> 1 bit
            boolean security = ByteOperator.getBit(typeWithFlags, SECURITY_INDEX);

            // skip two bytes as they represent reserved fields
            byteBuf.skipBytes(RESERVED_SKIP_LENGTH);

            // record count -> 8 bits
            byte recordCount = (byte) byteBuf.readUnsignedByte();

            // nonce -> 64 bits
            long nonce = byteBuf.readLong();

            List<LispMapRecord> mapRecords = Lists.newArrayList();
            for (int i = 0; i < recordCount; i++) {
                mapRecords.add(new MapRecordReader().readFrom(byteBuf));
            }

            return new DefaultReplyBuilder()
                        .withIsProbe(probe)
                        .withIsEtr(etr)
                        .withIsSecurity(security)
                        .withNonce(nonce)
                        .withMapRecords(mapRecords)
                        .build();
        }
    }

    /**
     * A LISP message writer for MapReply message.
     */
    public static final class ReplyWriter implements LispMessageWriter<LispMapReply> {

        private static final int REPLY_SHIFT_BIT = 4;

        private static final int PROBE_FLAG_SHIFT_BIT = 3;
        private static final int ETR_FLAG_SHIFT_BIT = 2;
        private static final int SECURITY_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, LispMapReply message) throws LispWriterException {

            // specify LISP message type
            byte msgType = (byte) (LispType.LISP_MAP_REPLY.getTypeCode() << REPLY_SHIFT_BIT);

            // probe flag
            byte probe = DISABLE_BIT;
            if (message.isProbe()) {
                probe = (byte) (ENABLE_BIT << PROBE_FLAG_SHIFT_BIT);
            }

            // etr flag
            byte etr = DISABLE_BIT;
            if (message.isEtr()) {
                etr = (byte) (ENABLE_BIT << ETR_FLAG_SHIFT_BIT);
            }

            // security flag
            byte security = DISABLE_BIT;
            if (message.isSecurity()) {
                security = (byte) (ENABLE_BIT << SECURITY_FLAG_SHIFT_BIT);
            }

            byteBuf.writeByte((byte) (msgType + probe + etr + security));

            // reserved field
            byteBuf.writeShort((short) UNUSED_ZERO);

            // record count
            byteBuf.writeByte(message.getMapRecords().size());

            // nonce
            byteBuf.writeLong(message.getNonce());

            // serialize map records
            MapRecordWriter writer = new MapRecordWriter();
            List<LispMapRecord> records = message.getMapRecords();

            for (int i = 0; i < records.size(); i++) {
                writer.writeTo(byteBuf, records.get(i));
            }
        }
    }
}
