/*
 * 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.onosproject.ospf.exceptions.OspfErrorType;
import org.onosproject.ospf.exceptions.OspfParseException;
import org.onosproject.ospf.protocol.lsa.LsaHeader;
import org.onosproject.ospf.protocol.lsa.OpaqueLsaHeader;
import org.onosproject.ospf.protocol.ospfpacket.OspfPacketHeader;
import org.onosproject.ospf.protocol.util.OspfPacketType;
import org.onosproject.ospf.protocol.util.OspfParameters;
import org.onosproject.ospf.protocol.util.OspfUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.ArrayList;
import java.util.List;

/**
 * Representation of an  OSPF Link State Acknowledgment Message.
 * Link State Acknowledgment Packets are OSPF packet type 5.
 * To make the flooding of LSAs reliable, flooded LSAs are explicitly
 * acknowledged. This acknowledgment is accomplished through the
 * sending and receiving of Link State Acknowledgment packets.
 * Multiple LSAs can be acknowledged in a single Link State Acknowledgment packet.
 */
public class LsAcknowledge 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 #   |       5       |         Packet length         |
       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
       |                          Router ID                            |
       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
       |                           Area ID                             |
       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
       |           Checksum            |             AuType            |
       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
       |                       Authentication                          |
       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
       |                       Authentication                          |
       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
       |                                                               |
       +-                                                             -+
       |                                                               |
       +-                         An LSA Header                       -+
       |                                                               |
       +-                                                             -+
       |                                                               |
       +-                                                             -+
       |                                                               |
       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
       |                              ...                              |
 */
    private static final Logger log = LoggerFactory.getLogger(LsAcknowledge.class);
    private List<LsaHeader> linkStateHeaders = new ArrayList<>();

    /**
     * Creates an instance of Link State Acknowledgment instance.
     */
    public LsAcknowledge() {
    }

    /**
     * Creates an instance of Link State Acknowledgment instance.
     *
     * @param ospfHeader OSPF header instance.
     */
    public LsAcknowledge(OspfPacketHeader ospfHeader) {
        populateHeader(ospfHeader);
    }

    /**
     * Gets ls headers.
     *
     * @return ls headers
     */
    public List<LsaHeader> getLinkStateHeaders() {
        return linkStateHeaders;
    }

    /**
     * Adds link state header to list.
     *
     * @param lsaHeader LSA header
     */
    public void addLinkStateHeader(LsaHeader lsaHeader) {
        if (!linkStateHeaders.contains(lsaHeader)) {
            linkStateHeaders.add(lsaHeader);
        }
    }

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

    @Override
    public void readFrom(ChannelBuffer channelBuffer) throws OspfParseException {
        try {
            //add all the LSA Headers - one header is of 20 bytes
            while (channelBuffer.readableBytes() >= OspfUtil.LSA_HEADER_LENGTH) {
                LsaHeader header = OspfUtil.readLsaHeader(channelBuffer);
                //add the LSAHeader to acknowledge
                addLinkStateHeader(header);
            }

        } catch (Exception e) {
            log.debug("Error::LsAckPacket:: {}", e.getMessage());
            throw new OspfParseException(OspfErrorType.MESSAGE_HEADER_ERROR, OspfErrorType.BAD_MESSAGE_LENGTH);
        }
    }

    @Override
    public byte[] asBytes() {
        byte[] lsAckMessage = null;

        byte[] lsAckHeader = getLsAckAsByteArray();
        byte[] lsAckBody = getLsAckBodyAsByteArray();
        lsAckMessage = Bytes.concat(lsAckHeader, lsAckBody);

        return lsAckMessage;
    }

    /**
     * Gets LSAcknowledge as byte array.
     *
     * @return byte array
     */
    public byte[] getLsAckAsByteArray() {
        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::LsAckPacket:: {}", e.getMessage());
            return Bytes.toArray(headerLst);
        }

        return Bytes.toArray(headerLst);
    }

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

        try {
            for (LsaHeader lsaHeader : linkStateHeaders) {
                if (lsaHeader.lsType() == OspfParameters.LINK_LOCAL_OPAQUE_LSA ||
                        lsaHeader.lsType() == OspfParameters.AREA_LOCAL_OPAQUE_LSA ||
                        lsaHeader.lsType() == OspfParameters.AS_OPAQUE_LSA) {
                    OpaqueLsaHeader header = (OpaqueLsaHeader) lsaHeader;
                    bodyLst.addAll(Bytes.asList(header.getOpaqueLsaHeaderAsByteArray()));
                } else {
                    bodyLst.addAll(Bytes.asList(lsaHeader.getLsaHeaderAsByteArray()));
                }
            }
        } catch (Exception e) {
            log.debug("Error::getLsAckBodyAsByteArray {}", e.getMessage());
            return Bytes.toArray(bodyLst);
        }

        return Bytes.toArray(bodyLst);
    }

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