/*
 * Copyright 2016 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();
    }
}