/*
 * 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-20
 * https://tools.ietf.org/html/draft-ietf-lisp-lcaf-20#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);
        }
        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)
                .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 = LispLcafAddress.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() - LispLcafAddress.COMMON_HEADER_SIZE < lcafAddress.getLength()) {
                rtrRlocAddresses.add(new AfiAddressReader().readFrom(byteBuf));
            }

            return new NatAddressBuilder()
                    .withReserved1(lcafAddress.getReserved1())
                    .withReserved2(lcafAddress.getReserved2())
                    .withFlag(lcafAddress.getFlag())
                    .withLength(lcafAddress.getLength())
                    .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();
            LispLcafAddress.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));
            }

            LispLcafAddress.updateLength(lcafIndex, byteBuf);
        }
    }
}
