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

import com.google.common.base.MoreObjects;

import org.jboss.netty.buffer.ChannelBuffer;
import org.onlab.packet.IpAddress;
import org.onosproject.bgpio.exceptions.BgpParseException;
import org.onosproject.bgpio.types.BgpErrorType;
import org.onosproject.bgpio.types.BgpValueType;
import org.onosproject.bgpio.types.WideCommunityAttrHeader;
import org.onosproject.bgpio.types.WideCommunityExcludeTarget;
import org.onosproject.bgpio.types.WideCommunityInteger;
import org.onosproject.bgpio.types.WideCommunityIpV4Neighbour;
import org.onosproject.bgpio.types.WideCommunityParameter;
import org.onosproject.bgpio.types.WideCommunityTarget;
import org.onosproject.bgpio.util.Validation;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

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

/**
 * Provides implementation of wide community path attribute.
 */
public class WideCommunity implements BgpValueType {

    private static final Logger log = LoggerFactory.getLogger(WideCommunity.class);
    public static final byte TYPE = (byte) 129;
    public static final short LENGTH = 4;
    public static final byte TYPE_LENGTH_SIZE = 3;
    public static final byte FLAGS = (byte) 0x90;
    private WideCommunityAttrHeader wideCommunityHeader;
    private int community;
    private int localAsn;
    private int contextAsn;
    private WideCommunityTarget target;
    private WideCommunityExcludeTarget excludeTarget;
    private WideCommunityParameter parameter;

    /**
     * Creates an instance of wide community.
     *
     * @param wideCommunityHeader wide community header
     * @param community wide community
     * @param localAsn local ASN number
     * @param contextAsn context ASN number
     * @param target wide community include target
     * @param excludeTarget wide community exclude target
     * @param parameter wide community parameter
     */
    public WideCommunity(WideCommunityAttrHeader wideCommunityHeader, int community, int localAsn, int contextAsn,
                             WideCommunityTarget target, WideCommunityExcludeTarget excludeTarget,
                             WideCommunityParameter parameter) {
        this.wideCommunityHeader = wideCommunityHeader;
        this.community = community;
        this.localAsn = localAsn;
        this.contextAsn = contextAsn;
        this.target = target;
        this.excludeTarget = excludeTarget;
        this.parameter = parameter;
    }

    /**
     * Returns object of this class with specified values.
     *
     * @param community wide community
     * @param localAsn local ASN number
     * @param contextAsn context ASN number
     * @param target wide community include target
     * @param excludeTarget wide community exclude target
     * @param parameter wide community parameter
     * @return object of WideCommunityAttr
     */
    public static WideCommunity of(WideCommunityAttrHeader wideCommunityHeader, int community, int localAsn,
                                       int contextAsn, WideCommunityTarget target,
                                       WideCommunityExcludeTarget excludeTarget, WideCommunityParameter parameter) {
        return new WideCommunity(wideCommunityHeader, community, localAsn, contextAsn, target, excludeTarget,
                                     parameter);
    }

    /**
     * Returns wide community value.
     *
     * @return wide community value
     */
    public int community() {
        return community;
    }

    /**
     * Sets wide community value.
     *
     * @param community wide community value
     */
    public void setCommunity(int community) {
        this.community = community;
    }

    /**
     * Returns wide community local autonomous number.
     *
     * @return local autonomous number
     */
    public int localAsn() {
        return localAsn;
    }

    /**
     * Sets wide community local autonomous number.
     *
     * @param localAsn local autonomous number
     */
    public void setLocalAsn(int localAsn) {
        this.localAsn = localAsn;
    }

    /**
     * Returns wide community context autonomous number.
     *
     * @return contest autonomous number
     */
    public int contextAsn() {
        return contextAsn;
    }

    /**
     * Sets wide community context autonomous number.
     *
     * @param contextAsn context autonomous number
     */
    public void setContextAsn(int contextAsn) {
        this.contextAsn = contextAsn;
    }

    /**
     * Returns wide community target.
     *
     * @return wide community target
     */
    public WideCommunityTarget target() {
        return target;
    }

    /**
     * Sets wide community target.
     *
     * @param target wide community target
     */
    public void setTarget(WideCommunityTarget target) {
        this.target = target;
    }

    /**
     * Returns wide community exclude target.
     *
     * @return wide community exclude target
     */
    public WideCommunityExcludeTarget excludeTarget() {
        return excludeTarget;
    }

    /**
     * Sets wide community exclude target.
     *
     * @param excludeTarget wide community texclude arget
     */
    public void setExcludeTarget(WideCommunityExcludeTarget excludeTarget) {
        this.excludeTarget = excludeTarget;
    }

    /**
     * Returns wide community parameter.
     *
     * @return wide community parameter
     */
    public WideCommunityParameter parameter() {
        return parameter;
    }

    /**
     * Sets wide community parameter.
     *
     * @param parameter wide community parameter
     */
    public void setParameter(WideCommunityParameter parameter) {
        this.parameter = parameter;
    }

    @Override
    public int hashCode() {
        return Objects.hash(wideCommunityHeader, community, localAsn, contextAsn, target, excludeTarget, parameter);
    }

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

        if (obj instanceof WideCommunity) {
            WideCommunity other = (WideCommunity) obj;
            return Objects.equals(wideCommunityHeader, other.wideCommunityHeader)
                    && Objects.equals(community, other.community) && Objects.equals(localAsn, other.localAsn)
                    && Objects.equals(contextAsn, other.contextAsn) && Objects.equals(target, other.target)
                    && Objects.equals(excludeTarget, other.excludeTarget) && Objects.equals(parameter, other.parameter);
        }
        return false;
    }

    @Override
    public int write(ChannelBuffer c) {
        int iTargetLenIndex;
        int length;
        int iLenStartIndex = c.writerIndex();
        c.writeByte(FLAGS); // TODO: update flag value
        c.writeByte(TYPE);

        int iLengthIndex = c.writerIndex();
        c.writeShort(0);

        wideCommunityHeader.write(c);

        int iComLengthIndex = c.writerIndex();
        c.writeShort(0);

        c.writeInt(community);
        c.writeInt(localAsn);
        c.writeInt(contextAsn);

        if (target() != null) {
            c.writeByte(WideCommunityTarget.TYPE);
            iTargetLenIndex = c.writerIndex();
            c.writeShort(0); // length

            target.write(c);

            length = c.writerIndex() - iTargetLenIndex;
            c.setShort(iTargetLenIndex, (short) (length - 2));
        }

        if (excludeTarget() != null) {
            c.writeByte(WideCommunityExcludeTarget.TYPE);
            iTargetLenIndex = c.writerIndex();
            c.writeShort(0); // length

            excludeTarget.write(c);

            length = c.writerIndex() - iTargetLenIndex;
            c.setShort(iTargetLenIndex, (short) (length - 2));
        }

        if (parameter() != null) {
            c.writeByte(WideCommunityParameter.TYPE);
            iTargetLenIndex = c.writerIndex();
            c.writeShort(0); // length

            parameter.write(c);

            length = c.writerIndex() - iTargetLenIndex;
            c.setShort(iTargetLenIndex, (short) (length - 2));
        }

        length = c.writerIndex() - iComLengthIndex;
        c.setShort(iComLengthIndex, (short) (length - 2));

        length = c.writerIndex() - iLengthIndex;
        c.setShort(iLengthIndex, (short) (length - 2));

        return c.writerIndex() - iLenStartIndex;
    }

    /**
     * Reads the wide community attribute.
     *
     * @param c ChannelBuffer
     * @return object of WideCommunityAttr
     * @throws BgpParseException while parsing BgpPrefixAttrRouteTag
     */
    public static WideCommunity read(ChannelBuffer c) throws BgpParseException {

        WideCommunityAttrHeader wideCommunityHeader;
        int community;
        int localAsn;
        int contextAsn;
        WideCommunityTarget target = null;
        WideCommunityExcludeTarget excludeTarget = null;
        WideCommunityParameter parameter = null;

        short length = c.readShort();

        if (c.readableBytes() < length) {
            Validation.validateLen(BgpErrorType.UPDATE_MESSAGE_ERROR, BgpErrorType.ATTRIBUTE_LENGTH_ERROR, length);
        }

        wideCommunityHeader = WideCommunityAttrHeader.read(c);
        if ((c.readableBytes() < 12) || (c.readableBytes() < wideCommunityHeader.length())) {
            Validation.validateLen(BgpErrorType.UPDATE_MESSAGE_ERROR, BgpErrorType.ATTRIBUTE_LENGTH_ERROR, length);
        }

        community = c.readInt();
        localAsn = c.readInt();
        contextAsn = c.readInt();

        while (c.readableBytes() > 0) {

            if (c.readableBytes() < TYPE_LENGTH_SIZE) {
                Validation.validateLen(BgpErrorType.UPDATE_MESSAGE_ERROR, BgpErrorType.ATTRIBUTE_LENGTH_ERROR,
                                       c.readableBytes());
            }

            byte type = c.readByte();
            length = c.readShort();

            if (c.readableBytes() < length) {
                Validation.validateLen(BgpErrorType.UPDATE_MESSAGE_ERROR, BgpErrorType.ATTRIBUTE_LENGTH_ERROR,
                                       c.readableBytes());
            }

            if (type == WideCommunityTarget.TYPE) {
                target = WideCommunityTarget.read(c);
            } else if (type == WideCommunityExcludeTarget.TYPE) {
                excludeTarget = WideCommunityExcludeTarget.read(c);
            } else if (type == WideCommunityParameter.TYPE) {
                parameter = WideCommunityParameter.read(c);
            }
        }
        return new WideCommunity(wideCommunityHeader, community, localAsn, contextAsn,
                                     target, excludeTarget, parameter);
    }

    /**
     * Encode wide community target(s).
     *
     * @param c channel buffer
     * @param targetTlv wide community include/exclude target
     */
    public static void encodeWideCommunityTlv(ChannelBuffer c,
                                    List<BgpValueType> targetTlv) {

        /*
         +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
         |  IPV4Neig(8)  |   Length:                   8 |
         +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
         | local                                               10101010  |
         +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
         | remote                                              10101010  |
         +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
         * */
        List<BgpValueType> target = targetTlv;
        if (target == null) {
           log.debug("target is null");
           return;
        }
        Iterator<BgpValueType> listIterator = targetTlv.iterator();

        while (listIterator.hasNext()) {
            BgpValueType attr = listIterator.next();
            if (attr instanceof WideCommunityIpV4Neighbour) {
                WideCommunityIpV4Neighbour ipv4Neig = (WideCommunityIpV4Neighbour) attr;
                ipv4Neig.write(c);
            } else if (attr instanceof WideCommunityInteger) {
                WideCommunityInteger integer = (WideCommunityInteger) attr;
                integer.write(c);
            }
        }
        return;
    }

    /**
     * Decode wide community target(s).
     *
     * @param c channel buffer
     * @return target list
     * @throws BgpParseException on decode error
     */
    public static List<BgpValueType> decodeWideCommunityTlv(ChannelBuffer c) throws BgpParseException {
        List<BgpValueType> targetTlv = new ArrayList<>();

        while (c.readableBytes() > 0) {
            if (c.readableBytes() < TYPE_LENGTH_SIZE) {
                Validation.validateLen(BgpErrorType.UPDATE_MESSAGE_ERROR, BgpErrorType.ATTRIBUTE_LENGTH_ERROR,
                                       c.readableBytes());
            }

            byte atomType = c.readByte();
            short atomLength = c.readShort();

            if (c.readableBytes() < atomLength) {
                Validation.validateLen(BgpErrorType.UPDATE_MESSAGE_ERROR, BgpErrorType.ATTRIBUTE_LENGTH_ERROR,
                                       atomLength);
            }

            if (atomType == WideCommunityIpV4Neighbour.TYPE) {
                ChannelBuffer tempBuf = c.readBytes(atomLength);

                WideCommunityIpV4Neighbour wideCommAtom = new WideCommunityIpV4Neighbour();

                while (tempBuf.readableBytes() > 0) {
                    wideCommAtom.add(IpAddress.valueOf(tempBuf.readInt()),
                                     IpAddress.valueOf(tempBuf.readInt()));
                }
                targetTlv.add(wideCommAtom);
            } else if (atomType == WideCommunityInteger.TYPE) {
                ChannelBuffer tempBuf = c.readBytes(atomLength);
                List<Integer> integer = new ArrayList<>();
                while (tempBuf.readableBytes() > 0) {
                    integer.add(tempBuf.readInt());
                }
                targetTlv.add(new WideCommunityInteger(integer));
            } else {
                Validation.validateLen(BgpErrorType.UPDATE_MESSAGE_ERROR, BgpErrorType.MALFORMED_ATTRIBUTE_LIST,
                                       atomLength);
            }
        }
        return targetTlv;
    }

    @Override
    public short getType() {
        return TYPE;
    }

    @Override
    public int compareTo(Object o) {
        // TODO:
        return 0;
    }

    @Override
    public String toString() {
        return MoreObjects.toStringHelper(getClass())
                .omitNullValues()
                .add("FLAGS", FLAGS)
                .add("wideCommunityHeader", wideCommunityHeader)
                .add("community", community)
                .add("localAsn", localAsn)
                .add("contextAsn", contextAsn)
                .add("target", target)
                .add("excludeTarget", excludeTarget)
                .add("parameter", parameter).toString();
    }
}
