/*
 * 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) 254; /* TODO: IANA Assigned */
    public static final short LENGTH = 4;
    public static final byte TYPE_LENGTH_SIZE = 3;
    public static final byte FLAGS = (byte) 0x40;
    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);

        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() - 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();
    }
}
