/*
 * Copyright 2015 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;

import com.google.common.base.MoreObjects;
import org.jboss.netty.buffer.ChannelBuffer;
import org.onosproject.bgpio.exceptions.BgpParseException;
import org.onosproject.bgpio.util.Constants;
import org.onosproject.bgpio.util.Validation;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

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

/**
 * Provides Implementation of As4Path BGP Path Attribute.
 */
public class As4Path implements BgpValueType {
    private static final Logger log = LoggerFactory.getLogger(AsPath.class);
    public static final byte AS4PATH_TYPE = 17;
    public static final byte ASNUM_SIZE = 4;
    public static final byte FLAGS = (byte) 0x40;

    private List<Integer> as4pathSet;
    private List<Integer> as4pathSeq;

    /**
     * Initialize fields.
     */
    public As4Path() {
        this.as4pathSeq = null;
        this.as4pathSet = null;
    }

    /**
     * Constructor to initialize parameters.
     *
     * @param as4pathSet AS4path Set
     * @param as4pathSeq AS4path Sequence
     */
    public As4Path(List<Integer> as4pathSet, List<Integer> as4pathSeq) {
        this.as4pathSeq = as4pathSeq;
        this.as4pathSet = as4pathSet;
    }

    /**
     * Reads from the channel buffer and parses As4Path.
     *
     * @param cb ChannelBuffer
     * @return object of As4Path
     * @throws BgpParseException while parsing As4Path
     */
    public static As4Path read(ChannelBuffer cb) throws BgpParseException {
        List<Integer> as4pathSet = new ArrayList<>();
        List<Integer> as4pathSeq = new ArrayList<>();
        ChannelBuffer tempCb = cb.copy();
        Validation validation = Validation.parseAttributeHeader(cb);

        if (cb.readableBytes() < validation.getLength()) {
            Validation.validateLen(BgpErrorType.UPDATE_MESSAGE_ERROR, BgpErrorType.ATTRIBUTE_LENGTH_ERROR,
                    validation.getLength());
        }
        //if fourth bit is set length is read as short otherwise as byte , len includes type, length and value
        int len = validation.isShort() ? validation.getLength() + Constants.TYPE_AND_LEN_AS_SHORT : validation
                .getLength() + Constants.TYPE_AND_LEN_AS_BYTE;
        ChannelBuffer data = tempCb.readBytes(len);
        if (validation.getFirstBit() && !validation.getSecondBit() && validation.getThirdBit()) {
            throw new BgpParseException(BgpErrorType.UPDATE_MESSAGE_ERROR, BgpErrorType.ATTRIBUTE_FLAGS_ERROR, data);
        }

        ChannelBuffer tempBuf = cb.readBytes(validation.getLength());
        while (tempBuf.readableBytes() > 0) {
            byte pathSegType = tempBuf.readByte();
            //no of ASes
            byte pathSegLen = tempBuf.readByte();
            //length = no of Ases * ASnum size (4 bytes)
            int length = pathSegLen * ASNUM_SIZE;
            if (tempBuf.readableBytes() < length) {
                Validation.validateLen(BgpErrorType.UPDATE_MESSAGE_ERROR,
                        BgpErrorType.ATTRIBUTE_LENGTH_ERROR, length);
            }
            ChannelBuffer aspathBuf = tempBuf.readBytes(length);
            while (aspathBuf.readableBytes() > 0) {
                int asNum;
                asNum = aspathBuf.readInt();
                switch (pathSegType) {
                case AsPath.ASPATH_SET_TYPE:
                    as4pathSet.add(asNum);
                    break;
                case AsPath.ASPATH_SEQ_TYPE:
                    as4pathSeq.add(asNum);
                    break;
                default: log.debug("Other type Not Supported:" + pathSegType);
                }
            }
        }
        return new As4Path(as4pathSet, as4pathSeq);
    }

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

    /**
     * Returns list of ASNum in AS4path Sequence.
     *
     * @return list of ASNum in AS4path Sequence
     */
    public List<Integer> as4PathSeq() {
        return this.as4pathSeq;
    }

    /**
     * Returns list of ASNum in AS4path Set.
     *
     * @return list of ASNum in AS4path Set
     */
    public List<Integer> as4PathSet() {
        return this.as4pathSet;
    }

    @Override
    public int hashCode() {
        return Objects.hash(as4pathSet, as4pathSeq);
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj) {
            return true;
        }
        if (obj instanceof As4Path) {
            As4Path other = (As4Path) obj;
            return Objects.equals(as4pathSet, other.as4pathSet) && Objects.equals(as4pathSeq, other.as4pathSeq);
        }
        return false;
    }

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

    @Override
    public int write(ChannelBuffer cb) {

        int iLenStartIndex = cb.writerIndex();

        cb.writeByte(FLAGS);
        cb.writeByte(getType());
        if ((as4pathSet != null) && (as4pathSeq != null)) {
            int iAsLenIndex = cb.writerIndex();
            cb.writeByte(0);
            cb.writeByte(AsPath.ASPATH_SEQ_TYPE);
            cb.writeByte(as4pathSeq.size());

            for (int j = 0; j < as4pathSeq.size(); j++) {
                cb.writeInt(as4pathSeq.get(j));
            }

            int asLen = cb.writerIndex() - iAsLenIndex;
            cb.setByte(iAsLenIndex, (byte) (asLen - 1));
        } else {
            cb.writeByte(0);
        }
        return cb.writerIndex() - iLenStartIndex;
    }

    @Override
    public int compareTo(Object o) {
        // TODO Auto-generated method stub
        return 0;
    }
}
