/*
 * 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.bgpio.protocol.flowspec;

import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;
import java.util.Objects;

import org.jboss.netty.buffer.ChannelBuffer;
import org.jboss.netty.buffer.ChannelBuffers;
import org.onosproject.bgpio.types.BgpFsDestinationPortNum;
import org.onosproject.bgpio.types.BgpFsDestinationPrefix;
import org.onosproject.bgpio.types.BgpFsDscpValue;
import org.onosproject.bgpio.types.BgpFsFragment;
import org.onosproject.bgpio.types.BgpFsIcmpCode;
import org.onosproject.bgpio.types.BgpFsIcmpType;
import org.onosproject.bgpio.types.BgpFsIpProtocol;
import org.onosproject.bgpio.types.BgpFsPacketLength;
import org.onosproject.bgpio.types.BgpFsPortNum;
import org.onosproject.bgpio.types.BgpFsSourcePortNum;
import org.onosproject.bgpio.types.BgpFsSourcePrefix;
import org.onosproject.bgpio.types.BgpFsTcpFlags;
import org.onosproject.bgpio.types.BgpValueType;
import org.onosproject.bgpio.types.RouteDistinguisher;
import org.onosproject.bgpio.util.Constants;

import com.google.common.base.MoreObjects;

/**
 * This Class stores flow specification components and action.
 */
public class BgpFlowSpecNlri {
    private List<BgpValueType> flowSpecComponents;
    private List<BgpValueType> fsActionTlv;
    private RouteDistinguisher routeDistinguisher;
    public static final short FLOW_SPEC_LEN = 240;

    /**
     * Flow specification details object constructor with the parameter.
     *
     * @param flowSpecComponents flow specification components
     */
    public BgpFlowSpecNlri(List<BgpValueType> flowSpecComponents) {
        this.flowSpecComponents = flowSpecComponents;
    }

    /**
     * Flow specification details object constructor.
     *
     */
    public BgpFlowSpecNlri() {

    }

    /**
     * Returns flow specification action tlv.
     *
     * @return flow specification action tlv
     */
    public List<BgpValueType> fsActionTlv() {
        return this.fsActionTlv;
    }

    /**
     * Set flow specification action tlv.
     *
     * @param fsActionTlv flow specification action tlv
     */
    public void setFsActionTlv(List<BgpValueType> fsActionTlv) {
        this.fsActionTlv = fsActionTlv;
    }

    /**
     * Returns route distinguisher for the flow specification components.
     *
     * @return route distinguisher for the flow specification components
     */
    public RouteDistinguisher routeDistinguisher() {
        return this.routeDistinguisher;
    }

    /**
     * Set route distinguisher for flow specification component.
     *
     * @param routeDistinguisher route distinguisher
     */
    public void setRouteDistinguiher(RouteDistinguisher routeDistinguisher) {
        this.routeDistinguisher = routeDistinguisher;
    }

    /**
     * Returns flow specification components.
     *
     * @return flow specification components
     */
    public List<BgpValueType> flowSpecComponents() {
        return this.flowSpecComponents;
    }

    /**
     * Sets flow specification components.
     *
     * @param flowSpecComponents flow specification components
     */
    public void setFlowSpecComponents(List<BgpValueType> flowSpecComponents) {
        this.flowSpecComponents = flowSpecComponents;
    }

    @Override
    public int hashCode() {
        return Objects.hash(flowSpecComponents);
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj) {
            return true;
        }

        if (obj instanceof BgpFlowSpecNlri) {
            int countObjSubTlv = 0;
            int countOtherSubTlv = 0;
            boolean isCommonSubTlv = true;
            BgpFlowSpecNlri other = (BgpFlowSpecNlri) obj;
            Iterator<BgpValueType> objListIterator = other.flowSpecComponents.iterator();
            countOtherSubTlv = other.flowSpecComponents.size();
            countObjSubTlv = flowSpecComponents.size();
            if (countObjSubTlv != countOtherSubTlv) {
                return false;
            } else {
                while (objListIterator.hasNext() && isCommonSubTlv) {
                    BgpValueType subTlv = objListIterator.next();
                    if (flowSpecComponents.contains(subTlv) && other.flowSpecComponents.contains(subTlv)) {
                        isCommonSubTlv = Objects.equals(flowSpecComponents.get(flowSpecComponents.indexOf(subTlv)),
                                            other.flowSpecComponents.get(other.flowSpecComponents.indexOf(subTlv)));
                    } else {
                        isCommonSubTlv = false;
                    }
                }
                return isCommonSubTlv;
            }
        }
        return false;
    }

    /**
     * Write flow type to channel buffer.
     *
     * @param tlv flow type
     * @param cb channel buffer
     */
    public static void writeFlowType(BgpValueType tlv, ChannelBuffer cb) {

        switch (tlv.getType()) {
            case Constants.BGP_FLOWSPEC_DST_PREFIX:
                BgpFsDestinationPrefix fsDstPrefix = (BgpFsDestinationPrefix) tlv;
                fsDstPrefix.write(cb);
                break;
            case Constants.BGP_FLOWSPEC_SRC_PREFIX:
                BgpFsSourcePrefix fsSrcPrefix = (BgpFsSourcePrefix) tlv;
                fsSrcPrefix.write(cb);
                break;
            case Constants.BGP_FLOWSPEC_IP_PROTO:
                BgpFsIpProtocol fsIpProtocol = (BgpFsIpProtocol) tlv;
                fsIpProtocol.write(cb);
                break;
            case Constants.BGP_FLOWSPEC_PORT:
                BgpFsPortNum fsPortNum = (BgpFsPortNum) tlv;
                fsPortNum.write(cb);
                break;
            case Constants.BGP_FLOWSPEC_DST_PORT:
                BgpFsDestinationPortNum fsDstPortNum = (BgpFsDestinationPortNum) tlv;
                fsDstPortNum.write(cb);
                break;
            case Constants.BGP_FLOWSPEC_SRC_PORT:
                BgpFsSourcePortNum fsSrcPortNum = (BgpFsSourcePortNum) tlv;
                fsSrcPortNum.write(cb);
                break;
            case Constants.BGP_FLOWSPEC_ICMP_TP:
                BgpFsIcmpType fsIcmpType = (BgpFsIcmpType) tlv;
                fsIcmpType.write(cb);
                break;
            case Constants.BGP_FLOWSPEC_ICMP_CD:
                BgpFsIcmpCode fsIcmpCode = (BgpFsIcmpCode) tlv;
                fsIcmpCode.write(cb);
                break;
            case Constants.BGP_FLOWSPEC_TCP_FLAGS:
                BgpFsTcpFlags fsTcpFlags = (BgpFsTcpFlags) tlv;
                fsTcpFlags.write(cb);
                break;
            case Constants.BGP_FLOWSPEC_PCK_LEN:
                BgpFsPacketLength fsPacketLen = (BgpFsPacketLength) tlv;
                fsPacketLen.write(cb);
                break;
            case Constants.BGP_FLOWSPEC_DSCP:
                BgpFsDscpValue fsDscpVal = (BgpFsDscpValue) tlv;
                fsDscpVal.write(cb);
                break;
            case Constants.BGP_FLOWSPEC_FRAGMENT:
                BgpFsFragment fsFragment = (BgpFsFragment) tlv;
                fsFragment.write(cb);
                break;
            default:
                break;
        }
        return;
    }

    /**
     * Update buffer with identical flow types.
     *
     * @param cb channel buffer
     */
    public static void updateBufferIdenticalFlowTypes(ChannelBuffer cb, BgpFlowSpecNlri bgpFlowSpecNlri) {

        List<BgpValueType> flowSpec = bgpFlowSpecNlri.flowSpecComponents();
        ListIterator<BgpValueType> listIterator = flowSpec.listIterator();

        while (listIterator.hasNext()) {
            ChannelBuffer flowSpecTmpBuff = ChannelBuffers.dynamicBuffer();
            int tmpBuffStartIndx = flowSpecTmpBuff.writerIndex();

            BgpValueType tlv = listIterator.next();
            writeFlowType(tlv, flowSpecTmpBuff);

            /* RFC 5575: section 4,  If the NLRI length value is smaller than 240 (0xf0 hex), the length
                                     field can be encoded as a single octet.  Otherwise, it is encoded as
                                     an extended-length 2-octet values */
            int len = flowSpecTmpBuff.writerIndex() - tmpBuffStartIndx;
            if (len >= FLOW_SPEC_LEN) {
                cb.writeShort(len);
            } else {
                cb.writeByte(len);
            }
            //Copy from bynamic buffer to channel buffer
            cb.writeBytes(flowSpecTmpBuff);
        }
        return;
    }

    /**
     * Update buffer with non-identical flow types.
     *
     * @param cb channel buffer
     */
    public static void updateBufferNonIdenticalFlowTypes(ChannelBuffer cb, BgpFlowSpecNlri bgpFlowSpecNlri) {
        ChannelBuffer flowSpecTmpBuff = ChannelBuffers.dynamicBuffer();
        List<BgpValueType> flowSpec = bgpFlowSpecNlri.flowSpecComponents();
        ListIterator<BgpValueType> listIterator = flowSpec.listIterator();
        int tmpBuffStartIndx = flowSpecTmpBuff.writerIndex();

        flowSpec = bgpFlowSpecNlri.flowSpecComponents();
        listIterator = flowSpec.listIterator();

        while (listIterator.hasNext()) {
            BgpValueType tlv = listIterator.next();
            writeFlowType(tlv, flowSpecTmpBuff);
        }

        /* RFC 5575: section 4,  If the NLRI length value is smaller than 240 (0xf0 hex), the length
                                 field can be encoded as a single octet.  Otherwise, it is encoded as
                                 an extended-length 2-octet values */
        int len = flowSpecTmpBuff.writerIndex() - tmpBuffStartIndx;
        if (len >= FLOW_SPEC_LEN) {
            cb.writeShort(len);
        } else {
            cb.writeByte(len);
        }
        //Copy from bynamic buffer to channel buffer
        cb.writeBytes(flowSpecTmpBuff);
    }

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