/*
 * 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 LispAfiAddress.AfiAddressReader().readFrom(byteBuf);
            LispAfiAddress msRlocAddress = new LispAfiAddress.AfiAddressReader().readFrom(byteBuf);
            LispAfiAddress privateEtrRlocAddress = new LispAfiAddress.AfiAddressReader().readFrom(byteBuf);

            List<LispAfiAddress> rtrRlocAddresses = Lists.newArrayList();
            for (int i = 0; i < lcafAddress.getLength(); i++) {
                rtrRlocAddresses.add(new LispAfiAddress.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 {

            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));
            }
        }
    }
}
