/*
 * 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 com.google.common.collect.ImmutableList;
import com.google.common.collect.Lists;
import io.netty.buffer.ByteBuf;
import org.onosproject.lisp.msg.exceptions.LispParseError;
import org.onosproject.lisp.msg.exceptions.LispReaderException;
import org.onosproject.lisp.msg.exceptions.LispWriterException;

import java.util.List;
import java.util.Objects;

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

/**
 * Network Address Translation (NAT) address class.
 * <p>
 * Instance ID type is defined in draft-ietf-lisp-lcaf-22
 * https://tools.ietf.org/html/draft-ietf-lisp-lcaf-22#page-12
 *
 * <pre>
 * {@literal
 *  0                   1                   2                   3
 *  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 * |           AFI = 16387         |     Rsvd1     |     Flags     |
 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 * |   Type = 7    |     Rsvd2     |             Length            |
 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 * |       MS UDP Port Number      |      ETR UDP Port Number      |
 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 * |              AFI = x          |  Global ETR RLOC Address  ... |
 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 * |              AFI = x          |       MS RLOC Address  ...    |
 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 * |              AFI = x          | Private ETR RLOC Address  ... |
 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 * |              AFI = x          |      RTR RLOC Address 1 ...   |
 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 * |              AFI = x          |      RTR RLOC Address k ...   |
 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 * }</pre>
 */
public final class LispNatLcafAddress extends LispLcafAddress {

    private final short msUdpPortNumber;
    private final short etrUdpPortNumber;
    private final LispAfiAddress globalEtrRlocAddress;
    private final LispAfiAddress msRlocAddress;
    private final LispAfiAddress privateEtrRlocAddress;
    private final List<LispAfiAddress> rtrRlocAddresses;

    /**
     * Initializes NAT type LCAF address.
     *
     * @param reserved2             reserved2
     * @param length                length
     * @param msUdpPortNumber       Map Server (MS) UDP port number
     * @param etrUdpPortNumber      ETR UDP port number
     * @param globalEtrRlocAddress  global ETR RLOC address
     * @param msRlocAddress         Map Server (MS) RLOC address
     * @param privateEtrRlocAddress private ETR RLOC address
     * @param rtrRlocAddresses      a collection of RTR RLOC addresses
     */
    private LispNatLcafAddress(byte reserved2, short length, short msUdpPortNumber,
                               short etrUdpPortNumber, LispAfiAddress globalEtrRlocAddress,
                               LispAfiAddress msRlocAddress, LispAfiAddress privateEtrRlocAddress,
                               List<LispAfiAddress> rtrRlocAddresses) {
        super(LispCanonicalAddressFormatEnum.NAT, reserved2, length);
        this.msUdpPortNumber = msUdpPortNumber;
        this.etrUdpPortNumber = etrUdpPortNumber;
        this.globalEtrRlocAddress = globalEtrRlocAddress;
        this.msRlocAddress = msRlocAddress;
        this.privateEtrRlocAddress = privateEtrRlocAddress;
        this.rtrRlocAddresses = ImmutableList.copyOf(rtrRlocAddresses);
    }

    /**
     * Obtains Map Server UDP port number.
     *
     * @return Map Server UDP port number
     */
    public short getMsUdpPortNumber() {
        return msUdpPortNumber;
    }

    /**
     * Obtains ETR UDP port number.
     *
     * @return ETR UDP port number
     */
    public short getEtrUdpPortNumber() {
        return etrUdpPortNumber;
    }

    /**
     * Obtains global ETR RLOC address.
     *
     * @return global ETR
     */
    public LispAfiAddress getGlobalEtrRlocAddress() {
        return globalEtrRlocAddress;
    }

    /**
     * Obtains Map Server RLOC address.
     *
     * @return Map Server RLOC address
     */
    public LispAfiAddress getMsRlocAddress() {
        return msRlocAddress;
    }

    /**
     * Obtains private ETR RLOC address.
     *
     * @return private ETR RLOC address
     */
    public LispAfiAddress getPrivateEtrRlocAddress() {
        return privateEtrRlocAddress;
    }

    /**
     * Obtains a collection of RTR RLOC addresses.
     *
     * @return a collection of RTR RLOC addresses
     */
    public List<LispAfiAddress> getRtrRlocAddresses() {
        return ImmutableList.copyOf(rtrRlocAddresses);
    }

    @Override
    public int hashCode() {
        return Objects.hash(msUdpPortNumber, etrUdpPortNumber,
                globalEtrRlocAddress, msRlocAddress, privateEtrRlocAddress);
    }

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

        if (obj instanceof LispNatLcafAddress) {
            final LispNatLcafAddress other = (LispNatLcafAddress) obj;
            return Objects.equals(this.msUdpPortNumber, other.msUdpPortNumber) &&
                    Objects.equals(this.etrUdpPortNumber, other.etrUdpPortNumber) &&
                    Objects.equals(this.globalEtrRlocAddress, other.globalEtrRlocAddress) &&
                    Objects.equals(this.msRlocAddress, other.msRlocAddress) &&
                    Objects.equals(this.privateEtrRlocAddress, other.privateEtrRlocAddress) &&
                    Objects.equals(this.rtrRlocAddresses, other.rtrRlocAddresses);
        }
        return false;
    }

    @Override
    public String toString() {
        return toStringHelper(this)
                .add("Map Server UDP port number", msUdpPortNumber)
                .add("ETR UDP port number", etrUdpPortNumber)
                .add("global ETR RLOC address", globalEtrRlocAddress)
                .add("Map Server RLOC address", msRlocAddress)
                .add("private ETR RLOC address", privateEtrRlocAddress)
                .add("RTR RLOC addresses", rtrRlocAddresses)
                .toString();
    }

    public static final class NatAddressBuilder extends LcafAddressBuilder<NatAddressBuilder> {

        private short msUdpPortNumber;
        private short etrUdpPortNumber;
        private LispAfiAddress globalEtrRlocAddress;
        private LispAfiAddress msRlocAddress;
        private LispAfiAddress privateEtrRlocAddress;
        private List<LispAfiAddress> rtrRlocAddresses = Lists.newArrayList();

        /**
         * Sets Map Server UDP port number.
         *
         * @param msUdpPortNumber Map Server UDP port number
         * @return NatAddressBuilder object
         */
        public NatAddressBuilder withMsUdpPortNumber(short msUdpPortNumber) {
            this.msUdpPortNumber = msUdpPortNumber;
            return this;
        }

        /**
         * Sets ETR UDP port number.
         *
         * @param etrUdpPortNumber ETR UDP port number
         * @return NatAddressBuilder object
         */
        public NatAddressBuilder withEtrUdpPortNumber(short etrUdpPortNumber) {
            this.etrUdpPortNumber = etrUdpPortNumber;
            return this;
        }

        /**
         * Sets global ETR RLOC address.
         *
         * @param globalEtrRlocAddress global ETR RLOC address
         * @return NatAddressBuilder object
         */
        public NatAddressBuilder withGlobalEtrRlocAddress(LispAfiAddress globalEtrRlocAddress) {
            this.globalEtrRlocAddress = globalEtrRlocAddress;
            return this;
        }

        /**
         * Sets Map Server RLOC address.
         *
         * @param msRlocAddress Map Server RLOC address
         * @return NatAddressBuilder object
         */
        public NatAddressBuilder withMsRlocAddress(LispAfiAddress msRlocAddress) {
            this.msRlocAddress = msRlocAddress;
            return this;
        }

        /**
         * Sets private ETR RLOC address.
         *
         * @param privateEtrRlocAddress private ETR RLOC address
         * @return NatAddressBuilder object
         */
        public NatAddressBuilder withPrivateEtrRlocAddress(LispAfiAddress privateEtrRlocAddress) {
            this.privateEtrRlocAddress = privateEtrRlocAddress;
            return this;
        }

        /**
         * Sets RTR RLOC addresses.
         *
         * @param rtrRlocAddresses a collection of RTR RLOC addresses
         * @return NatAddressBuilder object
         */
        public NatAddressBuilder withRtrRlocAddresses(List<LispAfiAddress> rtrRlocAddresses) {
            if (rtrRlocAddresses != null) {
                this.rtrRlocAddresses = ImmutableList.copyOf(rtrRlocAddresses);
            }
            return this;
        }

        public LispNatLcafAddress build() {

            // TODO: need to do null check

            return new LispNatLcafAddress(reserved2, length, msUdpPortNumber,
                    etrUdpPortNumber, globalEtrRlocAddress, msRlocAddress,
                    privateEtrRlocAddress, rtrRlocAddresses);
        }
    }

    /**
     * NAT LCAF address reader class.
     */
    public static class NatLcafAddressReader
            implements LispAddressReader<LispNatLcafAddress> {

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

            LispLcafAddress lcafAddress = deserializeCommon(byteBuf);

            short msUdpPortNumber = (short) byteBuf.readUnsignedShort();
            short etrUdpPortNumber = (short) byteBuf.readUnsignedShort();

            LispAfiAddress globalEtrRlocAddress = new AfiAddressReader().readFrom(byteBuf);
            LispAfiAddress msRlocAddress = new AfiAddressReader().readFrom(byteBuf);
            LispAfiAddress privateEtrRlocAddress = new AfiAddressReader().readFrom(byteBuf);

            List<LispAfiAddress> rtrRlocAddresses = Lists.newArrayList();

            while (byteBuf.readerIndex() - COMMON_HEADER_SIZE < lcafAddress.getLength()) {
                rtrRlocAddresses.add(new AfiAddressReader().readFrom(byteBuf));
            }

            return new NatAddressBuilder()
                            .withMsUdpPortNumber(msUdpPortNumber)
                            .withEtrUdpPortNumber(etrUdpPortNumber)
                            .withGlobalEtrRlocAddress(globalEtrRlocAddress)
                            .withMsRlocAddress(msRlocAddress)
                            .withPrivateEtrRlocAddress(privateEtrRlocAddress)
                            .withRtrRlocAddresses(rtrRlocAddresses)
                            .build();
        }
    }

    /**
     * NAT LCAF address writer class.
     */
    public static class NatLcafAddressWriter
            implements LispAddressWriter<LispNatLcafAddress> {

        @Override
        public void writeTo(ByteBuf byteBuf, LispNatLcafAddress address)
                throws LispWriterException {

            int lcafIndex = byteBuf.writerIndex();
            serializeCommon(byteBuf, address);

            byteBuf.writeShort(address.getMsUdpPortNumber());
            byteBuf.writeShort(address.getEtrUdpPortNumber());

            AfiAddressWriter writer = new LispAfiAddress.AfiAddressWriter();
            writer.writeTo(byteBuf, address.getGlobalEtrRlocAddress());
            writer.writeTo(byteBuf, address.getMsRlocAddress());
            writer.writeTo(byteBuf, address.getPrivateEtrRlocAddress());

            List<LispAfiAddress> rtrRlocAddresses = address.getRtrRlocAddresses();

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

            updateLength(lcafIndex, byteBuf);
        }
    }
}
