/*
 * 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.lsa.types;

import com.google.common.base.MoreObjects;
import com.google.common.base.Objects;
import com.google.common.primitives.Bytes;
import org.jboss.netty.buffer.ChannelBuffer;
import org.onosproject.ospf.controller.OspfLsaType;
import org.onosproject.ospf.exceptions.OspfErrorType;
import org.onosproject.ospf.exceptions.OspfParseException;
import org.onosproject.ospf.protocol.lsa.OpaqueLsaHeader;
import org.onosproject.ospf.protocol.lsa.TlvHeader;
import org.onosproject.ospf.protocol.lsa.tlvtypes.LinkTlv;
import org.onosproject.ospf.protocol.lsa.tlvtypes.OpaqueTopLevelTlvTypes;
import org.onosproject.ospf.protocol.lsa.tlvtypes.RouterTlv;
import org.onosproject.ospf.protocol.util.OspfParameters;

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

/**
 * Representation of an Opaque LSA of type area local (10).
 */
public class OpaqueLsa10 extends OpaqueLsaHeader {
    /*
      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
     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
     |            LS age             |     Options   |   9, 10 or 11 |
     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
     |  Opaque Type  |               Opaque ID                       |
     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
     |                      Advertising Router                       |
     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
     |                      LS Sequence Number                       |
     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
     |         LS checksum           |           Length              |
     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
     |                                                               |
     +                                                               +
     |                      Opaque Information                       |
     +                                                               +
     |                              ...                              |

        Opaque LSA format
        REFERENCE : RFC 5250
    */
    private List<TopLevelTlv> topLevelValues = new ArrayList<>();
    private byte[] opaqueInfo = null;

    /**
     * Creates an instance of Opaque type 10 LSA.
     *
     * @param lsaHeader LSA header instance
     */
    public OpaqueLsa10(OpaqueLsaHeader lsaHeader) {
        populateHeader(lsaHeader);
    }

    /**
     * Returns the list of top level TLVs.
     *
     * @return list of top level TLVs
     */
    public List<TopLevelTlv> topLevelValues() {
        return topLevelValues;
    }

    /**
     * Adds TLV value.
     *
     * @param value TLV value
     */
    public void addValue(TopLevelTlv value) {
        topLevelValues.add(value);
    }

    /**
     * Reads from channel buffer and populate instance.
     *
     * @param channelBuffer channelBuffer instance
     * @throws OspfParseException might throws exception while parsing buffer
     */
    public void readFrom(ChannelBuffer channelBuffer) throws OspfParseException {

        try {
            if (this.opaqueId() == OspfParameters.TRAFFIC_ENGINEERING) {
                while (channelBuffer.readableBytes() > 0) {
                    TlvHeader tlvHeader = new TlvHeader();
                    tlvHeader.setTlvType(channelBuffer.readUnsignedShort());
                    tlvHeader.setTlvLength(channelBuffer.readUnsignedShort());
                    if (tlvHeader.tlvType() == OpaqueTopLevelTlvTypes.ROUTER.value()) {
                        RouterTlv routerTlv = new RouterTlv(tlvHeader);
                        routerTlv.readFrom(channelBuffer.readBytes(tlvHeader.tlvLength()));
                        this.addValue(routerTlv);
                    } else if (tlvHeader.tlvType() == OpaqueTopLevelTlvTypes.LINK.value()) {
                        LinkTlv linkTlv = new LinkTlv(tlvHeader);
                        linkTlv.readFrom(channelBuffer.readBytes(tlvHeader.tlvLength()));
                        this.addValue(linkTlv);
                    }
                }
            } else {
                int length = channelBuffer.readableBytes();
                opaqueInfo = new byte[length];
                channelBuffer.readBytes(opaqueInfo, 0, length);
            }

        } catch (Exception e) {
            log.debug("Error::OpaqueLsa10:: {}", e.getMessage());
            throw new OspfParseException(OspfErrorType.OSPF_MESSAGE_ERROR,
                                         OspfErrorType.BAD_MESSAGE);
        }
    }

    /**
     * Returns instance as bytes.
     *
     * @return instance as bytes
     * @throws OspfParseException might throws exception while parsing packet
     */
    public byte[] asBytes() throws OspfParseException {

        byte[] lsaMessage = null;
        byte[] lsaHeader = getOpaqueLsaHeaderAsByteArray();
        byte[] lsaBody = getLsaBodyAsByteArray();
        lsaMessage = Bytes.concat(lsaHeader, lsaBody);
        return lsaMessage;

    }

    /**
     * Gets the LSA body as byte array.
     *
     * @return the lsa body as byte array
     * @throws OspfParseException might throws exception while parsing packet
     */
    public byte[] getLsaBodyAsByteArray() throws OspfParseException {
        List<Byte> bodyLst = new ArrayList<>();
        if (this.opaqueId() == 1) {
            for (TopLevelTlv tlv : this.topLevelValues) {
                //Check the sub type of lsa and build bytes accordingly
                if (tlv instanceof RouterTlv) {
                    RouterTlv routerTlv = (RouterTlv) tlv;
                    bodyLst.addAll(Bytes.asList(routerTlv.asBytes()));
                } else if (tlv instanceof LinkTlv) {
                    LinkTlv linkTlv = (LinkTlv) tlv;
                    bodyLst.addAll(Bytes.asList(linkTlv.asBytes()));
                }
            }
        } else {
            return opaqueInfo;
        }

        return Bytes.toArray(bodyLst);
    }

    @Override
    public OspfLsaType getOspfLsaType() {
        return OspfLsaType.AREA_LOCAL_OPAQUE_LSA;
    }

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

    @Override
    public boolean equals(Object o) {
        if (this == o) {
            return true;
        }
        if (o == null || getClass() != o.getClass()) {
            return false;
        }
        OpaqueLsa10 that = (OpaqueLsa10) o;
        return Objects.equal(topLevelValues, that.topLevelValues) &&
                Arrays.equals(opaqueInfo, that.opaqueInfo);
    }

    @Override
    public int hashCode() {
        return Objects.hashCode(Arrays.hashCode(opaqueInfo), topLevelValues);
    }
}