/*
 * 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.pcepio.protocol.ver1;

import java.util.LinkedList;
import java.util.ListIterator;

import org.jboss.netty.buffer.ChannelBuffer;
import org.onosproject.pcepio.exceptions.PcepParseException;
import org.onosproject.pcepio.protocol.PcepCloseMsg;
import org.onosproject.pcepio.protocol.PcepMessageReader;
import org.onosproject.pcepio.protocol.PcepMessageWriter;
import org.onosproject.pcepio.protocol.PcepType;
import org.onosproject.pcepio.protocol.PcepVersion;
import org.onosproject.pcepio.types.PcepObjectHeader;
import org.onosproject.pcepio.types.PcepValueType;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.google.common.base.MoreObjects;

/**
 * Provides PCEP Close Message.
 */
class PcepCloseMsgVer1 implements PcepCloseMsg {

    /*
     * RFC : 5440 , section : 6.8
     * <Close Message>           ::= <Common Header> <CLOSE>
     *
         0                   1                   2                   3
         0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
        +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
        | Ver |  Flags  |  Message-Type |       Message-Length          |
        +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
        | Object-Class  |   OT  |Res|P|I|   Object Length (bytes)       |
        +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
        |          Reserved             |      Flags    |    Reason     |
        +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
        |                                                               |
        //                         Optional TLVs                       //
        |                                                               |
        +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
     */

    protected static final Logger log = LoggerFactory.getLogger(PcepCloseMsgVer1.class);

    // Pcep version: 1
    public static final byte PACKET_VERSION = 1;
    public static final int PACKET_MINIMUM_LENGTH = 12;
    public static final PcepType MSG_TYPE = PcepType.CLOSE;
    public static final byte CLOSE_OBJ_TYPE = 1;
    public static final byte CLOSE_OBJ_CLASS = 15;
    public static final byte CLOSE_OBJECT_VERSION = 1;
    public static final byte DEFAULT_REASON = 1; // Default reason to close
    public static final short CLOSE_OBJ_MINIMUM_LENGTH = 8;
    public static final int SHIFT_FLAG = 5;
    static final PcepObjectHeader DEFAULT_CLOSE_HEADER = new PcepObjectHeader(CLOSE_OBJ_CLASS, CLOSE_OBJ_TYPE,
            PcepObjectHeader.REQ_OBJ_OPTIONAL_PROCESS, PcepObjectHeader.RSP_OBJ_PROCESSED, CLOSE_OBJ_MINIMUM_LENGTH);

    private final PcepObjectHeader closeObjHeader;
    private byte yReason;
    private LinkedList<PcepValueType> llOptionalTlv;

    public static final PcepCloseMsgVer1.Reader READER = new Reader();

    /**
     * Reader class for reading close message for channel buffer.
     */
    static class Reader implements PcepMessageReader<PcepCloseMsg> {
        PcepObjectHeader closeObjHeader;
        byte yReason;
        // Optional TLV
        private LinkedList<PcepValueType> llOptionalTlv;

        @Override
        public PcepCloseMsg readFrom(ChannelBuffer cb) throws PcepParseException {

            if (cb.readableBytes() < PACKET_MINIMUM_LENGTH) {
                throw new PcepParseException("Packet size is less than the minimum length.");
            }
            // fixed value property version == 1
            byte version = cb.readByte();
            version = (byte) (version >> SHIFT_FLAG);
            if (version != PACKET_VERSION) {
                throw new PcepParseException("Wrong version. Expected=PcepVersion.PCEP_1(1), got=" + version);
            }
            // fixed value property type == 7
            byte type = cb.readByte();
            if (type != MSG_TYPE.getType()) {
                throw new PcepParseException("Wrong type. Expected=PcepType.CLOSE(7), got=" + type);
            }
            short length = cb.readShort();
            if (length < PACKET_MINIMUM_LENGTH) {
                throw new PcepParseException("Wrong length. Expected to be >= " + PACKET_MINIMUM_LENGTH + ", was: "
                        + length);
            }
            closeObjHeader = PcepObjectHeader.read(cb);
            // Reserved
            cb.readShort();
            // Flags
            cb.readByte();
            // Reason
            yReason = cb.readByte();
            // parse optional TLV
            llOptionalTlv = parseOptionalTlv(cb);
            return new PcepCloseMsgVer1(closeObjHeader, yReason, llOptionalTlv);
        }
    }

    /**
     * Parse the list of Optional Tlvs.
     *
     * @param cb channel buffer
     * @return list of Optional Tlvs
     * @throws PcepParseException when fails to parse optional tlvs
     */
    public static LinkedList<PcepValueType> parseOptionalTlv(ChannelBuffer cb) throws PcepParseException {

        LinkedList<PcepValueType> llOptionalTlv = new LinkedList<PcepValueType>();
        /*
         rfc 5440:
         Optional TLVs may be included within the CLOSE object body. The
         specification of such TLVs is outside the scope of this document.
         */
        return llOptionalTlv;
    }

    /**
     * constructor to initialize PCEP close Message with all the parameters.
     *
     * @param closeObjHeader object header for close message
     * @param yReason reason for closing the channel
     * @param llOptionalTlv list of optional tlvs
     */
    PcepCloseMsgVer1(PcepObjectHeader closeObjHeader, byte yReason, LinkedList<PcepValueType> llOptionalTlv) {

        this.closeObjHeader = closeObjHeader;
        this.yReason = yReason;
        this.llOptionalTlv = llOptionalTlv;
    }

    /**
     * Builder class for PCEP close message.
     */
    static class Builder implements PcepCloseMsg.Builder {

        // PCEP Close message fields
        private boolean bIsHeaderSet = false;
        private PcepObjectHeader closeObjHeader;
        private boolean bIsReasonSet = false;
        private byte yReason;
        private LinkedList<PcepValueType> llOptionalTlv = new LinkedList<PcepValueType>();

        private boolean bIsPFlagSet = false;
        private boolean bPFlag;

        private boolean bIsIFlagSet = false;
        private boolean bIFlag;

        @Override
        public PcepVersion getVersion() {
            return PcepVersion.PCEP_1;
        }

        @Override
        public PcepType getType() {
            return PcepType.CLOSE;
        }

        @Override
        public PcepCloseMsg build() {

            PcepObjectHeader closeObjHeader = this.bIsHeaderSet ? this.closeObjHeader : DEFAULT_CLOSE_HEADER;
            byte yReason = this.bIsReasonSet ? this.yReason : DEFAULT_REASON;

            if (bIsPFlagSet) {
                closeObjHeader.setPFlag(bPFlag);
            }

            if (bIsIFlagSet) {
                closeObjHeader.setIFlag(bIFlag);
            }
            return new PcepCloseMsgVer1(closeObjHeader, yReason, this.llOptionalTlv);
        }

        @Override
        public PcepObjectHeader getCloseObjHeader() {
            return this.closeObjHeader;
        }

        @Override
        public Builder setCloseObjHeader(PcepObjectHeader obj) {
            this.closeObjHeader = obj;
            this.bIsHeaderSet = true;
            return this;
        }

        @Override
        public byte getReason() {
            return this.yReason;
        }

        @Override
        public Builder setReason(byte value) {
            this.yReason = value;
            this.bIsReasonSet = true;
            return this;
        }

        @Override
        public Builder setOptionalTlv(LinkedList<PcepValueType> llOptionalTlv) {
            this.llOptionalTlv = llOptionalTlv;
            return this;
        }

        @Override
        public LinkedList<PcepValueType> getOptionalTlv() {
            return this.llOptionalTlv;
        }

        @Override
        public Builder setPFlag(boolean value) {
            this.bPFlag = value;
            this.bIsPFlagSet = true;
            return this;
        }

        @Override
        public Builder setIFlag(boolean value) {
            this.bIFlag = value;
            this.bIsIFlagSet = true;
            return this;
        }
    }

    @Override
    public void writeTo(ChannelBuffer cb) throws PcepParseException {
        WRITER.write(cb, this);
    }

    static final Writer WRITER = new Writer();

    /**
     * Writer class for writing close message to channel buffer.
     */
    static class Writer implements PcepMessageWriter<PcepCloseMsgVer1> {

        @Override
        public void write(ChannelBuffer cb, PcepCloseMsgVer1 message) throws PcepParseException {
            int startIndex = cb.writerIndex();
            // first 3 bits set to version
            cb.writeByte((byte) (PACKET_VERSION << SHIFT_FLAG));
            // message type
            cb.writeByte(MSG_TYPE.getType());
            // length is length of variable message, will be updated at the end
            // Store the position of message
            // length in buffer
            int msgLenIndex = cb.writerIndex();
            cb.writeShort((short) 0);
            int objStartIndex = cb.writerIndex();
            int objLenIndex = message.closeObjHeader.write(cb);
            if (objLenIndex <= 0) {
                throw new PcepParseException("Failed to write Close object header.");
            }
            // first 3 bits set to version
            cb.writeShort(0); // Reserved
            cb.writeByte(0); // Flags
            cb.writeByte(message.yReason);
            // Pack optional TLV
            packOptionalTlv(cb, message);
            int length = cb.writerIndex() - objStartIndex;
            cb.setShort(objLenIndex, (short) length);
            // will be helpful during print().
            message.closeObjHeader.setObjLen((short) length);
            // As per RFC the length of object should be
            // multiples of 4
            int pad = length % 4;
            if (pad != 0) {
                pad = 4 - pad;
                for (int i = 0; i < pad; i++) {
                    cb.writeByte((byte) 0);
                }
                length = length + pad;
            }
            // update message length field
            length = cb.writerIndex() - startIndex;
            cb.setShort(msgLenIndex, (short) length);
        }

        public void packOptionalTlv(ChannelBuffer cb, PcepCloseMsgVer1 message) {

            LinkedList<PcepValueType> llOptionalTlv = message.llOptionalTlv;
            ListIterator<PcepValueType> listIterator = llOptionalTlv.listIterator();
            while (listIterator.hasNext()) {
                listIterator.next().write(cb);
            }
        }
    }

    @Override
    public PcepVersion getVersion() {
        return PcepVersion.PCEP_1;
    }

    @Override
    public PcepType getType() {
        return MSG_TYPE;
    }

    @Override
    public byte getReason() {
        return this.yReason;
    }

    @Override
    public void setReason(byte value) {
        this.yReason = value;
    }

    @Override
    public LinkedList<PcepValueType> getOptionalTlv() {
        return this.llOptionalTlv;
    }

    @Override
    public void setOptionalTlv(LinkedList<PcepValueType> llOptionalTlv) {
        this.llOptionalTlv = llOptionalTlv;
    }

    @Override
    public String toString() {
        return MoreObjects.toStringHelper(getClass())
                .add("closeObjectHeader", closeObjHeader).add("Reason", yReason)
                .add("OptionalTlvlist", llOptionalTlv).toString();
    }
}
