/*
 * 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.ospf.protocol.ospfpacket.types;

import com.google.common.base.MoreObjects;
import com.google.common.primitives.Bytes;
import org.jboss.netty.buffer.ChannelBuffer;
import org.onlab.packet.Ip4Address;
import org.onosproject.ospf.exceptions.OspfParseException;
import org.onosproject.ospf.protocol.ospfpacket.OspfPacketHeader;
import org.onosproject.ospf.protocol.ospfpacket.subtype.LsRequestPacket;
import org.onosproject.ospf.protocol.util.OspfPacketType;
import org.onosproject.ospf.protocol.util.OspfUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.net.InetAddress;
import java.util.ArrayList;
import java.util.List;

/**
 * Representation of an OSPF Link State Request packet.
 * Link State Request packets are OSPF packet type 3.  After exchanging
 * database description packets with a neighboring router, a router may
 * find that parts of its link-state database are out-of-date.  The
 * Link State Request packet is used to request the pieces of the
 * neighbor's database that are more up-to-date.
 */
public class LsRequest extends OspfPacketHeader {
    /*
        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
       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
       |   Version #   |       3       |         Packet length         |
       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
       |                          Router ID                            |
       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
       |                           Area ID                             |
       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
       |           Checksum            |             AuType            |
       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
       |                       Authentication                          |
       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
       |                       Authentication                          |
       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
       |                          LS type                              |
       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
       |                       Link State ID                           |
       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
       |                     Advertising Router                        |
       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
       |                              ...                              |

       LsRequest Message Format
       REFERENCE : RFC 2328
     */
    private static final Logger log = LoggerFactory.getLogger(LsRequest.class);
    private List<LsRequestPacket> linkStateRequests = new ArrayList<>();

    /**
     * Creates an instance of link state request packet.
     */
    public LsRequest() {
    }

    /**
     * Creates an instance of link state request packet.
     *
     * @param ospfHeader OSPF header instance.
     */
    public LsRequest(OspfPacketHeader ospfHeader) {
        populateHeader(ospfHeader);
    }

    /**
     * Adds link state request.
     *
     * @param lsRequestPacket ls request packet instance
     */
    public void addLinkStateRequests(LsRequestPacket lsRequestPacket) {
        if (!linkStateRequests.contains(lsRequestPacket)) {
            linkStateRequests.add(lsRequestPacket);
        }
    }

    /**
     * Gets link state request packet instance.
     *
     * @return link state request packet instance
     */
    public List<LsRequestPacket> getLinkStateRequests() {
        return linkStateRequests;
    }

    @Override
    public OspfPacketType ospfMessageType() {
        return OspfPacketType.LSREQUEST;
    }

    @Override
    public void readFrom(ChannelBuffer channelBuffer) throws OspfParseException {

        while (channelBuffer.readableBytes() >= OspfUtil.LSREQUEST_LENGTH) {
            LsRequestPacket lsRequestPacket = new LsRequestPacket();
            lsRequestPacket.setLsType(channelBuffer.readInt());
            byte[] tempByteArray = new byte[OspfUtil.FOUR_BYTES];
            channelBuffer.readBytes(tempByteArray, 0, OspfUtil.FOUR_BYTES);
            lsRequestPacket.setLinkStateId(Ip4Address.valueOf(tempByteArray).toString());
            tempByteArray = new byte[OspfUtil.FOUR_BYTES];
            channelBuffer.readBytes(tempByteArray, 0, OspfUtil.FOUR_BYTES);
            lsRequestPacket.setOwnRouterId(Ip4Address.valueOf(tempByteArray).toString());

            this.addLinkStateRequests(lsRequestPacket);
        }
    }

    @Override
    public byte[] asBytes() {
        byte[] lsrMessage = null;
        byte[] lsrHeader = getLsrHeaderAsByteArray();
        byte[] lsrBody = getLsrBodyAsByteArray();
        lsrMessage = Bytes.concat(lsrHeader, lsrBody);

        return lsrMessage;
    }

    /**
     * Gets LS request packet header as byte array.
     *
     * @return LS request packet header as byte array
     */
    public byte[] getLsrHeaderAsByteArray() {
        List<Byte> headerLst = new ArrayList<>();

        try {
            headerLst.add((byte) this.ospfVersion());
            headerLst.add((byte) this.ospfType());
            headerLst.addAll(Bytes.asList(OspfUtil.convertToTwoBytes(this.ospfPacLength())));
            headerLst.addAll(Bytes.asList(this.routerId().toOctets()));
            headerLst.addAll(Bytes.asList(this.areaId().toOctets()));
            headerLst.addAll(Bytes.asList(OspfUtil.convertToTwoBytes(this.checksum())));
            headerLst.addAll(Bytes.asList(OspfUtil.convertToTwoBytes(this.authType())));
            //Authentication is 0 always. Total 8 bytes consist of zero
            byte[] auth = new byte[OspfUtil.EIGHT_BYTES];
            headerLst.addAll(Bytes.asList(auth));
        } catch (Exception e) {
            log.debug("Error::getLsrBodyAsByteArray {}", e.getMessage());
            return Bytes.toArray(headerLst);
        }

        return Bytes.toArray(headerLst);
    }

    /**
     * Gets LS request packet body as byte array.
     *
     * @return LS request packet body as byte array
     */
    public byte[] getLsrBodyAsByteArray() {
        List<Byte> bodyLst = new ArrayList<>();

        try {
            for (LsRequestPacket lsrPacket : linkStateRequests) {
                bodyLst.addAll(Bytes.asList(OspfUtil.convertToFourBytes(lsrPacket.lsType())));
                bodyLst.addAll(Bytes.asList(InetAddress.getByName(lsrPacket.linkStateId()).getAddress()));
                bodyLst.addAll(Bytes.asList(InetAddress.getByName(lsrPacket.ownRouterId()).getAddress()));
            }
        } catch (Exception e) {
            log.debug("Error::getLsrBodyAsByteArray {}", e.getMessage());
            return Bytes.toArray(bodyLst);
        }

        return Bytes.toArray(bodyLst);
    }

    @Override
    public String toString() {
        return MoreObjects.toStringHelper(getClass())
                .omitNullValues()
                .add("linkStateRequests", linkStateRequests)
                .toString();
    }
}