/*
 * Copyright 2015-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.onlab.packet.pim;

import org.onlab.packet.DeserializationException;

import java.nio.ByteBuffer;
import java.text.MessageFormat;
import java.util.Arrays;

import static org.onlab.packet.PacketUtils.checkBufferLength;
import static org.onlab.packet.PacketUtils.checkInput;

/**
 * PIM HELLO option.
 */
public class PIMHelloOption {

    /*
     * PIM Option types.
     */
    public static final short OPT_HOLDTIME = 1;
    public static final short HOLDTIME_LENGTH = 2;
    public static final short DEFAULT_HOLDTIME = 105;

    public static final short OPT_PRUNEDELAY = 2;
    public static final short PRUNEDELAY_LENGTH = 4;
    public static final short DEFAULT_PRUNEDELAY = 500; // 500 ms
    public static final short DEFAULT_OVERRIDEINTERVAL = 2500; // 2500 ms

    public static final short OPT_PRIORITY = 19;
    public static final short PRIORITY_LENGTH = 4;
    public static final int DEFAULT_PRIORITY = 1;

    public static final short OPT_GENID = 20;
    public static final short GENID_LENGTH = 4;
    public static final int DEFAULT_GENID = 0;

    public static final short OPT_ADDRLIST = 24;

    public static final int MINIMUM_OPTION_LEN_BYTES = 4;

    // Values for this particular hello option.
    private short optType = 0;
    private short optLength = 0;
    private byte[] optValue;

    /**
     * Constructs a new hello option with no fields set.
     */
    public PIMHelloOption() {
    }

    /**
     * Set a PIM Hello option by type. The length and default value of the
     * type will be auto filled in by default.
     *
     * @param type hello option type
     */
    public PIMHelloOption(short type) {
        this.optType = type;
        switch (type) {
            case OPT_HOLDTIME:
                this.optLength = HOLDTIME_LENGTH;
                this.optValue = new byte[optLength];
                ByteBuffer.wrap(this.optValue).putShort(PIMHelloOption.DEFAULT_HOLDTIME);
                break;

            case OPT_PRUNEDELAY:
                this.optLength = PRUNEDELAY_LENGTH;
                this.optValue = new byte[this.optLength];
                ByteBuffer.wrap(this.optValue).putInt(PIMHelloOption.DEFAULT_PRUNEDELAY);
                break;

            case OPT_PRIORITY:
                this.optLength = PRIORITY_LENGTH;
                this.optValue = new byte[this.optLength];
                ByteBuffer.wrap(this.optValue).putInt(PIMHelloOption.DEFAULT_PRIORITY);
                break;

            case OPT_GENID:
                this.optLength = GENID_LENGTH;
                this.optValue = new byte[this.optLength];
                ByteBuffer.wrap(this.optValue).putInt(PIMHelloOption.DEFAULT_GENID);
                break;

            case OPT_ADDRLIST:
                this.optLength = 0;   // We don't know what the length will be yet.
                this.optValue = null;
                break;

            default:
                //log.error("Unkown option type: " + type + "\n" );
                return;
        }
    }

    public void setOptType(short type) {
        this.optType = type;
    }

    public short getOptType() {
        return this.optType;
    }

    public void setOptLength(short len) {
        this.optLength = len;
    }

    public short getOptLength() {
        return this.optLength;
    }

    public void setValue(ByteBuffer bb) {
        this.optValue = new byte[this.optLength];
        bb.get(this.optValue, 0, this.optLength);
    }

    public void setValue(byte[] value) {
        this.optValue = value;
    }

    public byte[] getValue() {
        return this.optValue;
    }

    /**
     * Creates a new PIM Hello option with the specified values.
     *
     * @param type hello option type
     * @param length option length
     * @param value option value
     * @return new PIM Hello option
     */
    public static PIMHelloOption create(short type, short length, ByteBuffer value) {
        PIMHelloOption option = new PIMHelloOption();
        option.setOptType(type);
        option.setOptLength(length);
        value.rewind();
        option.setValue(value);
        return option;
    }

    /**
     * Creates a new priority option.
     *
     * @param priority priority
     * @return priority option
     */
    public static PIMHelloOption createPriority(int priority) {
        return create(OPT_PRIORITY, PRIORITY_LENGTH,
                ByteBuffer.allocate(PRIORITY_LENGTH).putInt(priority));
    }

    /**
     * Creates a new hold time option.
     *
     * @param holdTime hold time
     * @return hold time option
     */
    public static PIMHelloOption createHoldTime(short holdTime) {
        return create(OPT_HOLDTIME, HOLDTIME_LENGTH,
                ByteBuffer.allocate(HOLDTIME_LENGTH).putShort(holdTime));
    }

    /**
     * Creates a new generation ID option with a particular generation ID.
     *
     * @param genId generation ID value
     * @return generation ID option
     */
    public static PIMHelloOption createGenID(int genId) {
        return create(OPT_GENID, GENID_LENGTH,
                ByteBuffer.allocate(GENID_LENGTH).putInt(genId));
    }

    /**
     * Creates a new LAN Prune Delay option.
     *
     * @param propagationDelay prune delay
     * @param overrideInterval override interval
     * @return prune delay option
     */
    public static PIMHelloOption createPruneDelay(short propagationDelay, short overrideInterval) {
        return create(OPT_PRUNEDELAY, PRUNEDELAY_LENGTH,
                ByteBuffer.allocate(PRUNEDELAY_LENGTH)
                        .putShort(propagationDelay)
                        .putShort(overrideInterval));
    }

    public static PIMHelloOption deserialize(ByteBuffer bb) throws DeserializationException {
        checkInput(bb.array(), bb.position(), bb.limit() - bb.position(), MINIMUM_OPTION_LEN_BYTES);

        PIMHelloOption opt = new PIMHelloOption();
        opt.setOptType(bb.getShort());
        opt.setOptLength(bb.getShort());

        checkBufferLength(bb.limit(), bb.position(), opt.getOptLength());
        opt.setValue(bb);

        return opt;
    }

    public byte[] serialize() {
        int len = MINIMUM_OPTION_LEN_BYTES + this.optLength;
        ByteBuffer bb = ByteBuffer.allocate(len);
        bb.putShort(this.optType);
        bb.putShort(this.optLength);
        bb.put(this.optValue);
        return bb.array();
    }

    public String toString() {
        return MessageFormat.format("Type: {0}, len: {1} value: {2}", this.optType, this.optLength,
                Arrays.toString(this.optValue));
    }

}
