/*
 * Copyright 2014-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.onlab.packet;

import java.nio.ByteBuffer;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;

import static com.google.common.base.MoreObjects.toStringHelper;
import static org.onlab.packet.PacketUtils.*;

/**
 * Representation of an LLDP Packet.
 */
public class LLDP extends BasePacket {
    public static final byte CHASSIS_TLV_TYPE = 1;
    public static final short CHASSIS_TLV_SIZE = 7;
    public static final byte CHASSIS_TLV_SUBTYPE = 4;

    public static final byte PORT_TLV_TYPE = 2;
    public static final short PORT_TLV_SIZE = 5;

    public static final byte PORT_TLV_COMPONENT_SUBTYPE = 2;
    public static final byte PORT_TLV_INTERFACE_NAME_SUBTYPE = 5;

    public static final byte TTL_TLV_TYPE = 3;
    public static final short TTL_TLV_SIZE = 2;

    protected LLDPTLV chassisId;
    protected LLDPTLV portId;
    protected LLDPTLV ttl;
    protected List<LLDPTLV> optionalTLVList;
    protected short ethType;

    public LLDP() {
        this.optionalTLVList = new LinkedList<>();
        this.ethType = Ethernet.TYPE_LLDP;
    }

    /**
     * @return the chassisId
     */
    public LLDPTLV getChassisId() {
        return this.chassisId;
    }

    /**
     * @param chassis the chassisId to set
     * @return this
     */
    public LLDP setChassisId(final LLDPTLV chassis) {
        this.chassisId = chassis;
        return this;
    }

    /**
     * @return the portId
     */
    public LLDPTLV getPortId() {
        return this.portId;
    }

    /**
     * @param portId the portId to set
     * @return this
     */
    public LLDP setPortId(final LLDPTLV portId) {
        this.portId = portId;
        return this;
    }

    /**
     * @return the ttl
     */
    public LLDPTLV getTtl() {
        return this.ttl;
    }

    /**
     * @param ttl the ttl to set
     * @return this
     */
    public LLDP setTtl(final LLDPTLV ttl) {
        this.ttl = ttl;
        return this;
    }

    /**
     * @return the optionalTLVList
     */
    public List<LLDPTLV> getOptionalTLVList() {
        return this.optionalTLVList;
    }

    /**
     * @param optionalTLVList the optionalTLVList to set
     * @return this
     */
    public LLDP setOptionalTLVList(final List<LLDPTLV> optionalTLVList) {
        this.optionalTLVList = optionalTLVList;
        return this;
    }

    /**
     * Adds additional TLV to optionalTLVList.
     * @param lldptlv the optional TLV to be added
     * @return this
     */
    public LLDP addOptionalTLV(final LLDPTLV lldptlv) {
        this.optionalTLVList.add(lldptlv);
        return this;
    }

    @Override
    public byte[] serialize() {
        int length = 2 + this.chassisId.getLength() + 2
                + this.portId.getLength() + 2 + this.ttl.getLength() + 2;
        for (final LLDPTLV tlv : this.optionalTLVList) {
            length += 2 + tlv.getLength();
        }

        final byte[] data = new byte[length];
        final ByteBuffer bb = ByteBuffer.wrap(data);
        bb.put(this.chassisId.serialize());
        bb.put(this.portId.serialize());
        bb.put(this.ttl.serialize());
        for (final LLDPTLV tlv : this.optionalTLVList) {
            bb.put(tlv.serialize());
        }
        bb.putShort((short) 0); // End of LLDPDU

        /*
         * if (this.parent != null && this.parent instanceof Ethernet) {
         * ((Ethernet) this.parent).setEtherType(this.ethType); }
         */

        return data;
    }


    /*
     * (non-Javadoc)
     *
     * @see java.lang.Object#hashCode()
     */
    @Override
    public int hashCode() {
        final int prime = 883;
        int result = super.hashCode();
        result = prime * result
                + (this.chassisId == null ? 0 : this.chassisId.hashCode());
        result = prime * result + this.optionalTLVList.hashCode();
        result = prime * result
                + (this.portId == null ? 0 : this.portId.hashCode());
        result = prime * result + (this.ttl == null ? 0 : this.ttl.hashCode());
        return result;
    }

    /*
     * (non-Javadoc)
     *
     * @see java.lang.Object#equals(java.lang.Object)
     */
    @Override
    public boolean equals(final Object obj) {
        if (this == obj) {
            return true;
        }
        if (!super.equals(obj)) {
            return false;
        }
        if (!(obj instanceof LLDP)) {
            return false;
        }
        final LLDP other = (LLDP) obj;
        if (this.chassisId == null) {
            if (other.chassisId != null) {
                return false;
            }
        } else if (!this.chassisId.equals(other.chassisId)) {
            return false;
        }
        if (!this.optionalTLVList.equals(other.optionalTLVList)) {
            return false;
        }
        if (this.portId == null) {
            if (other.portId != null) {
                return false;
            }
        } else if (!this.portId.equals(other.portId)) {
            return false;
        }
        if (this.ttl == null) {
            if (other.ttl != null) {
                return false;
            }
        } else if (!this.ttl.equals(other.ttl)) {
            return false;
        }
        return true;
    }

    /**
     * Deserializer function for LLDP packets.
     *
     * @return deserializer function
     */
    public static Deserializer<LLDP> deserializer() {
        return (data, offset, length) -> {
            checkInput(data, offset, length, 0);

            LLDP lldp = new LLDP();

            int currentIndex = 0;

            ByteBuffer bb = ByteBuffer.wrap(data, offset, length);
            LLDPTLV tlv;
            do {
                // Each new TLV must be a minimum of 2 bytes
                // (containing the type and length fields).
                currentIndex += 2;
                checkHeaderLength(length, currentIndex);

                tlv = new LLDPOrganizationalTLV().deserialize(bb);

                // if there was a failure to deserialize stop processing TLVs
                if (tlv == null) {
                    break;
                }
                switch (tlv.getType()) {
                    case 0x0:
                        // can throw this one away, it's just an end delimiter
                        break;
                    case 0x1:
                        lldp.chassisId = tlv;
                        break;
                    case 0x2:
                        lldp.portId = tlv;
                        break;
                    case 0x3:
                        lldp.ttl = tlv;
                        break;
                    default:
                        lldp.optionalTLVList.add(tlv);
                        break;
                }

                currentIndex += tlv.getLength();
            } while (tlv.getType() != 0);

            return lldp;
        };
    }

    @Override
    public String toString() {
        return toStringHelper(getClass())
                .add("chassisId", Arrays.toString(chassisId.getValue()))
                .add("portId", Arrays.toString(portId.getValue()))
                .add("ttl", Arrays.toString(ttl.getValue()))
                .add("ethType", Short.toString(ethType))
                .toString();

        // TODO: need to handle optionalTLVList
    }
}
