/*
 * 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.protocols.LispEidRecord.EidRecordReader;
import org.onosproject.lisp.msg.types.LispAfiAddress;
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.List;

import static com.google.common.base.MoreObjects.toStringHelper;
import static com.google.common.base.Preconditions.checkArgument;
import static org.onosproject.lisp.msg.protocols.LispEidRecord.EidRecordWriter;

/**
 * Default LISP map request message class.
 */
public final class DefaultLispMapRequest extends AbstractLispMessage
        implements LispMapRequest {

    private final long nonce;
    private final LispAfiAddress sourceEid;
    private final List<LispAfiAddress> itrRlocs;
    private final List<LispEidRecord> eidRecords;
    private final boolean authoritative;
    private final boolean mapDataPresent;
    private final boolean probe;
    private final boolean smr;
    private final boolean pitr;
    private final boolean smrInvoked;

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

    /**
     * A private constructor that protects object instantiation from external.
     *
     * @param nonce          nonce
     * @param sourceEid      source EID address
     * @param itrRlocs       a collection of ITR RLOCs
     * @param eidRecords     a collection of EID records
     * @param authoritative  authoritative flag
     * @param mapDataPresent map data present flag
     * @param probe          probe flag
     * @param smr            smr flag
     * @param pitr           pitr flag
     * @param smrInvoked     smrInvoked flag
     */
    private DefaultLispMapRequest(long nonce, LispAfiAddress sourceEid,
                                  List<LispAfiAddress> itrRlocs, List<LispEidRecord> eidRecords,
                                  boolean authoritative, boolean mapDataPresent, boolean probe,
                                  boolean smr, boolean pitr, boolean smrInvoked) {
        this.nonce = nonce;
        this.sourceEid = sourceEid;
        this.itrRlocs = itrRlocs;
        this.eidRecords = eidRecords;
        this.authoritative = authoritative;
        this.mapDataPresent = mapDataPresent;
        this.probe = probe;
        this.smr = smr;
        this.pitr = pitr;
        this.smrInvoked = smrInvoked;
    }

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

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

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

    @Override
    public boolean isAuthoritative() {
        return authoritative;
    }

    @Override
    public boolean isMapDataPresent() {
        return mapDataPresent;
    }

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

    @Override
    public boolean isSmr() {
        return smr;
    }

    @Override
    public boolean isPitr() {
        return pitr;
    }

    @Override
    public boolean isSmrInvoked() {
        return smrInvoked;
    }

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

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

    @Override
    public LispAfiAddress getSourceEid() {
        return sourceEid;
    }

    @Override
    public List<LispAfiAddress> getItrRlocs() {
        return ImmutableList.copyOf(itrRlocs);
    }

    @Override
    public List<LispEidRecord> getEids() {
        return ImmutableList.copyOf(eidRecords);
    }

    @Override
    public String toString() {
        return toStringHelper(this)
                .add("type", getType())
                .add("nonce", nonce)
                .add("source EID", sourceEid)
                .add("ITR rlocs", itrRlocs)
                .add("EID records", eidRecords)
                .add("authoritative", authoritative)
                .add("mapDataPresent", mapDataPresent)
                .add("probe", probe)
                .add("SMR", smr)
                .add("Proxy ITR", pitr)
                .add("SMR Invoked", smrInvoked).toString();
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) {
            return true;
        }
        if (o == null || getClass() != o.getClass()) {
            return false;
        }
        DefaultLispMapRequest that = (DefaultLispMapRequest) o;
        return Objects.equal(nonce, that.nonce) &&
                Objects.equal(sourceEid, that.sourceEid) &&
                Objects.equal(authoritative, that.authoritative) &&
                Objects.equal(mapDataPresent, that.mapDataPresent) &&
                Objects.equal(probe, that.probe) &&
                Objects.equal(smr, that.smr) &&
                Objects.equal(pitr, that.pitr) &&
                Objects.equal(smrInvoked, that.smrInvoked);
    }

    @Override
    public int hashCode() {
        return Objects.hashCode(nonce, sourceEid, authoritative,
                mapDataPresent, probe, smr, pitr, smrInvoked);
    }

    public static final class DefaultRequestBuilder implements RequestBuilder {

        private long nonce;
        private LispAfiAddress sourceEid;
        private List<LispAfiAddress> itrRlocs = Lists.newArrayList();
        private List<LispEidRecord> eidRecords = Lists.newArrayList();
        private boolean authoritative;
        private boolean mapDataPresent;
        private boolean probe;
        private boolean smr;
        private boolean pitr;
        private boolean smrInvoked;

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

        @Override
        public RequestBuilder withIsAuthoritative(boolean authoritative) {
            this.authoritative = authoritative;
            return this;
        }

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

        @Override
        public RequestBuilder withIsMapDataPresent(boolean mapDataPresent) {
            this.mapDataPresent = mapDataPresent;
            return this;
        }

        @Override
        public RequestBuilder withIsSmr(boolean smr) {
            this.smr = smr;
            return this;
        }

        @Override
        public RequestBuilder withIsPitr(boolean pitr) {
            this.pitr = pitr;
            return this;
        }

        @Override
        public RequestBuilder withIsSmrInvoked(boolean smrInvoked) {
            this.smrInvoked = smrInvoked;
            return this;
        }

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

        @Override
        public RequestBuilder withSourceEid(LispAfiAddress sourceEid) {
            this.sourceEid = sourceEid;
            return this;
        }

        @Override
        public RequestBuilder withItrRlocs(List<LispAfiAddress> itrRlocs) {
            if (itrRlocs != null) {
                this.itrRlocs = ImmutableList.copyOf(itrRlocs);
            }
            return this;
        }

        @Override
        public RequestBuilder withEidRecords(List<LispEidRecord> records) {
            if (records != null) {
                this.eidRecords = ImmutableList.copyOf(records);
            }
            return this;
        }

        @Override
        public LispMapRequest build() {

            checkArgument((itrRlocs != null) && (itrRlocs.size() > 0), "Must have an ITR RLOC entry");

            return new DefaultLispMapRequest(nonce, sourceEid, itrRlocs, eidRecords,
                    authoritative, mapDataPresent, probe, smr, pitr, smrInvoked);
        }
    }

    /**
     * A LISP message reader for MapRequest message.
     */
    public static final class RequestReader implements LispMessageReader<LispMapRequest> {

        private static final int AUTHORITATIVE_INDEX = 3;
        private static final int MAP_DATA_PRESENT_INDEX = 2;
        private static final int PROBE_INDEX = 1;
        private static final int SMR_INDEX = 0;
        private static final int PITR_INDEX = 7;
        private static final int SMR_INVOKED_INDEX = 6;

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

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

            byte typeWithFlags = byteBuf.readByte();

            // authoritative -> 1 bit
            boolean authoritative = ByteOperator.getBit(typeWithFlags, AUTHORITATIVE_INDEX);

            // mapDataPresent -> 1 bit
            boolean mapDataPresent = ByteOperator.getBit(typeWithFlags, MAP_DATA_PRESENT_INDEX);

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

            // smr -> 1 bit
            boolean smr = ByteOperator.getBit(typeWithFlags, SMR_INDEX);

            byte reservedWithFlags = byteBuf.readByte();

            // pitr -> 1 bit
            boolean pitr = ByteOperator.getBit(reservedWithFlags, PITR_INDEX);

            // smrInvoked -> 1 bit
            boolean smrInvoked = ByteOperator.getBit(reservedWithFlags, SMR_INVOKED_INDEX);

            // let's skip reserved field, only obtains ITR counter value
            // assume that first 3 bits are all set as 0,
            // remain 5 bits represent Itr Rloc Counter (IRC)
            int irc = byteBuf.readUnsignedByte();

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

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

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

            // deserialize a collection of RLOC addresses
            List<LispAfiAddress> itrRlocs = Lists.newArrayList();
            for (int i = 0; i < irc + 1; i++) {
                itrRlocs.add(new AfiAddressReader().readFrom(byteBuf));
            }

            // deserialize a collection of EID records
            List<LispEidRecord> eidRecords = Lists.newArrayList();
            for (int i = 0; i < recordCount; i++) {
                eidRecords.add(new EidRecordReader().readFrom(byteBuf));
            }

            return new DefaultRequestBuilder()
                        .withIsAuthoritative(authoritative)
                        .withIsMapDataPresent(mapDataPresent)
                        .withIsProbe(probe)
                        .withIsSmr(smr)
                        .withIsPitr(pitr)
                        .withIsSmrInvoked(smrInvoked)
                        .withNonce(nonce)
                        .withSourceEid(sourceEid)
                        .withEidRecords(eidRecords)
                        .withItrRlocs(itrRlocs)
                        .build();
        }
    }

    /**
     * A LISP message writer for MapRequest message.
     */
    public static final class RequestWriter implements LispMessageWriter<LispMapRequest> {

        private static final int REQUEST_SHIFT_BIT = 4;

        private static final int AUTHORITATIVE_SHIFT_BIT = 3;
        private static final int MAP_DATA_PRESENT_SHIFT_BIT = 2;
        private static final int PROBE_SHIFT_BIT = 1;

        private static final int PITR_SHIFT_BIT = 7;
        private static final int SMR_INVOKED_SHIFT_BIT = 6;

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

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

            // specify LISP message type
            byte msgType = (byte) (LispType.LISP_MAP_REQUEST.getTypeCode() << REQUEST_SHIFT_BIT);

            // authoritative flag
            byte authoritative = DISABLE_BIT;
            if (message.isAuthoritative()) {
                authoritative = (byte) (ENABLE_BIT << AUTHORITATIVE_SHIFT_BIT);
            }

            // map data present flag
            byte mapDataPresent = DISABLE_BIT;
            if (message.isMapDataPresent()) {
                mapDataPresent = (byte) (ENABLE_BIT << MAP_DATA_PRESENT_SHIFT_BIT);
            }

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

            // SMR flag
            byte smr = DISABLE_BIT;
            if (message.isSmr()) {
                smr = (byte) ENABLE_BIT;
            }

            byteBuf.writeByte((byte) (msgType + authoritative + mapDataPresent + probe + smr));

            // PITR flag bit
            byte pitr = DISABLE_BIT;
            if (message.isPitr()) {
                pitr = (byte) (ENABLE_BIT << PITR_SHIFT_BIT);
            }

            // SMR invoked flag bit
            byte smrInvoked = DISABLE_BIT;
            if (message.isSmrInvoked()) {
                smrInvoked = (byte) (ENABLE_BIT << SMR_INVOKED_SHIFT_BIT);
            }

            byteBuf.writeByte((byte) (pitr + smrInvoked));

            // ITR Rloc count
            byteBuf.writeByte((byte) message.getItrRlocs().size() - 1);

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

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

            // Source EID AFI with Source EID address
            AfiAddressWriter afiAddressWriter = new AfiAddressWriter();
            afiAddressWriter.writeTo(byteBuf, message.getSourceEid());

            // ITR RLOCs
            List<LispAfiAddress> rlocs = message.getItrRlocs();
            for (int i = 0; i < rlocs.size(); i++) {
                afiAddressWriter.writeTo(byteBuf, rlocs.get(i));
            }

            // EID records
            EidRecordWriter recordWriter = new EidRecordWriter();
            List<LispEidRecord> records = message.getEids();

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

            // TODO: handle Map-Reply record
        }
    }
}
