/*
 * Copyright 2016-present Open Networking Foundation
 *
 * 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.controller.OspfLsa;
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.lsa.types.AsbrSummaryLsa;
import org.onosproject.ospf.protocol.lsa.types.ExternalLsa;
import org.onosproject.ospf.protocol.lsa.types.NetworkLsa;
import org.onosproject.ospf.protocol.lsa.types.OpaqueLsa10;
import org.onosproject.ospf.protocol.lsa.types.OpaqueLsa11;
import org.onosproject.ospf.protocol.lsa.types.OpaqueLsa9;
import org.onosproject.ospf.protocol.lsa.types.RouterLsa;
import org.onosproject.ospf.protocol.lsa.types.SummaryLsa;
import org.onosproject.ospf.protocol.ospfpacket.OspfPacketHeader;
import org.onosproject.ospf.controller.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.LinkedList;
import java.util.List;

/**
 * Representation of an OSPF Link State Update packet.
 * Link State Update packets are OSPF packet type 4.  These packets
 * implement the flooding of LSAs.  Each Link State Update packet
 * carries a collection of LSAs one hop further from their origin.
 * Several LSAs may be included in a single packet.
 */
public class LsUpdate 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 #   |       4       |         Packet length         |
       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
       |                          Router ID                            |
       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
       |                           Area ID                             |
       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
       |           Checksum            |             AuType            |
       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
       |                       Authentication                          |
       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
       |                       Authentication                          |
       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
       |                            # LSAs                             |
       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
       |                                                               |
       +-                                                            +-+
       |                             LSAs                              |
       +-                                                            +-+
       |                              ...                              |
     */
    private static final Logger log = LoggerFactory.getLogger(LsUpdate.class);
    private int numberOfLsa;
    private List<OspfLsa> lsaList = new LinkedList<>();

    /**
     * Creates an instance of Link State Update packet.
     */
    public LsUpdate() {
    }

    /**
     * Creates an instance of Link State Update packet.
     *
     * @param ospfHeader ospf header instance.
     */
    public LsUpdate(OspfPacketHeader ospfHeader) {
        populateHeader(ospfHeader);
    }

    /**
     * Gets the LSA list.
     *
     * @return list of LSA
     */
    public List getLsaList() {
        return lsaList;
    }

    /**
     * Adds the LSA to list.
     *
     * @param lsa LSA
     */
    public void addLsa(OspfLsa lsa) {
        if (!lsaList.contains(lsa)) {
            lsaList.add(lsa);
        }
    }

    /**
     * Gets the number of LSA.
     *
     * @return number of LSA
     */
    public int noLsa() {
        return numberOfLsa;
    }

    /**
     * Sets number of LSA.
     *
     * @param numberOfLsa number of LSA
     */
    public void setNumberOfLsa(int numberOfLsa) {
        this.numberOfLsa = numberOfLsa;
    }


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

    @Override
    public void readFrom(ChannelBuffer channelBuffer) throws OspfParseException {
        try {
            //From header 4 bytes is number of lsa's
            this.setNumberOfLsa(channelBuffer.readInt());
            //get the remaining bytes represents Number of LSA's present. Add all the LSA's
            while (channelBuffer.readableBytes() > OspfUtil.LSA_HEADER_LENGTH) {

                LsaHeader header = OspfUtil.readLsaHeader(channelBuffer.readBytes(OspfUtil.LSA_HEADER_LENGTH));
                int lsaLength = header.lsPacketLen();
                int lsType = header.lsType();

                switch (lsType) {
                    case OspfParameters.LINK_LOCAL_OPAQUE_LSA:
                        OpaqueLsa9 opaqueLsa9 = new OpaqueLsa9((OpaqueLsaHeader) header);
                        opaqueLsa9.readFrom(channelBuffer.readBytes(lsaLength - OspfUtil.LSA_HEADER_LENGTH));
                        addLsa(opaqueLsa9);
                        break;
                    case OspfParameters.AREA_LOCAL_OPAQUE_LSA:
                        OpaqueLsa10 opaqueLsa10 = new OpaqueLsa10((OpaqueLsaHeader) header);
                        opaqueLsa10.readFrom(channelBuffer.readBytes(lsaLength - OspfUtil.LSA_HEADER_LENGTH));
                        addLsa(opaqueLsa10);
                        break;
                    case OspfParameters.AS_OPAQUE_LSA:
                        OpaqueLsa11 opaqueLsa11 = new OpaqueLsa11((OpaqueLsaHeader) header);
                        opaqueLsa11.readFrom(channelBuffer.readBytes(lsaLength - OspfUtil.LSA_HEADER_LENGTH));
                        addLsa(opaqueLsa11);
                        break;
                    case OspfParameters.ROUTER:
                        RouterLsa routerLsa = new RouterLsa(header);
                        routerLsa.readFrom(channelBuffer.readBytes(lsaLength - OspfUtil.LSA_HEADER_LENGTH));
                        addLsa(routerLsa);
                        break;
                    case OspfParameters.NETWORK:
                        NetworkLsa networkLsa = new NetworkLsa(header);
                        networkLsa.readFrom(channelBuffer.readBytes(lsaLength - OspfUtil.LSA_HEADER_LENGTH));
                        addLsa(networkLsa);
                        break;
                    case OspfParameters.ASBR_SUMMARY:
                        AsbrSummaryLsa asbrSummaryLsa = new AsbrSummaryLsa(header);
                        asbrSummaryLsa.readFrom(channelBuffer.readBytes(lsaLength - OspfUtil.LSA_HEADER_LENGTH));
                        addLsa(asbrSummaryLsa);
                        break;
                    case OspfParameters.SUMMARY:
                        SummaryLsa summaryLsa = new SummaryLsa(header);
                        summaryLsa.readFrom(channelBuffer.readBytes(lsaLength - OspfUtil.LSA_HEADER_LENGTH));
                        addLsa(summaryLsa);
                        break;
                    case OspfParameters.EXTERNAL_LSA:
                        ExternalLsa externalLsa = new ExternalLsa(header);
                        externalLsa.readFrom(channelBuffer.readBytes(lsaLength - OspfUtil.LSA_HEADER_LENGTH));
                        addLsa(externalLsa);
                        break;
                    default:
                        log.debug("LSUpdate::readLsUpdateBody::UnKnown LS Type: {}", lsType);
                        break;
                }
            }
        } catch (Exception e) {
            log.debug("Error::LsUpdate:: {}", e.getMessage());
            throw new OspfParseException(OspfErrorType.MESSAGE_HEADER_ERROR, OspfErrorType.BAD_MESSAGE_LENGTH);
        }
    }

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

        byte[] ospfHeader = getLsuHeaderAsByteArray();
        byte[] lsuBody = getLsuBodyAsByteArray();
        lsuMessage = Bytes.concat(ospfHeader, lsuBody);

        return lsuMessage;
    }

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

        return Bytes.toArray(headerLst);
    }

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

        try {
            //add number of LSA's
            bodyLst.addAll(Bytes.asList(OspfUtil.convertToFourBytes(this.noLsa())));
            //for each type of LSA's from the list get lsa bytes
            for (OspfLsa ospfLsa : lsaList) {
                //Check the type of lsa and build bytes accordingly
                switch (ospfLsa.getOspfLsaType().value()) {
                    case OspfParameters.LINK_LOCAL_OPAQUE_LSA:
                        OpaqueLsa9 opaqueLsa9 = (OpaqueLsa9) ospfLsa;
                        bodyLst.addAll(Bytes.asList(opaqueLsa9.asBytes()));
                        break;
                    case OspfParameters.AREA_LOCAL_OPAQUE_LSA:
                        OpaqueLsa10 opaqueLsa10 = (OpaqueLsa10) ospfLsa;
                        bodyLst.addAll(Bytes.asList(opaqueLsa10.asBytes()));
                        break;
                    case OspfParameters.AS_OPAQUE_LSA:
                        OpaqueLsa11 opaqueLsa11 = (OpaqueLsa11) ospfLsa;
                        bodyLst.addAll(Bytes.asList(opaqueLsa11.asBytes()));
                        break;
                    case OspfParameters.ROUTER:
                        RouterLsa routerLsa = (RouterLsa) ospfLsa;
                        bodyLst.addAll(Bytes.asList(routerLsa.asBytes()));
                        break;
                    case OspfParameters.NETWORK:
                        NetworkLsa networkLsa = (NetworkLsa) ospfLsa;
                        bodyLst.addAll(Bytes.asList(networkLsa.asBytes()));
                        break;
                    case OspfParameters.ASBR_SUMMARY:
                        AsbrSummaryLsa asbrSummaryLsa = (AsbrSummaryLsa) ospfLsa;
                        bodyLst.addAll(Bytes.asList(asbrSummaryLsa.asBytes()));
                        break;
                    case OspfParameters.SUMMARY:
                        SummaryLsa summaryLsa = (SummaryLsa) ospfLsa;
                        bodyLst.addAll(Bytes.asList(summaryLsa.asBytes()));
                        break;
                    case OspfParameters.EXTERNAL_LSA:
                        ExternalLsa externalLsa = (ExternalLsa) ospfLsa;
                        bodyLst.addAll(Bytes.asList(externalLsa.asBytes()));
                        break;
                    default:
                        log.debug("LSUpdate::getLsuBodyAsByteArray::UnKnown ospfLsa: {}", ospfLsa);
                        break;
                }
            }

        } catch (Exception e) {
            log.debug("Error::getLsuBodyAsByteArray {}", e.getMessage());
            return Bytes.toArray(bodyLst);
        }

        return Bytes.toArray(bodyLst);
    }

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