/*
 * Copyright 2017-present Open Networking Foundation
 *
 * 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.dhcp;

import com.google.common.base.MoreObjects;
import org.onlab.packet.BasePacket;
import org.onlab.packet.Deserializer;

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

public class Dhcp6Duid extends BasePacket {
    private static final int DEFAULT_LLT_LEN = 8;
    private static final int DEFAULT_EN_LEN = 6;
    private static final int DEFAULT_LL_LEN = 4;
    public enum DuidType {
        DUID_LLT((short) 1),
        DUID_EN((short) 2),
        DUID_LL((short) 3);

        private short value;
        DuidType(short value) {
            this.value = value;
        }

        public short getValue() {
            return value;
        }

        public static DuidType of(short type) {
            switch (type) {
                case 1:
                    return DUID_LLT;
                case 2:
                    return DUID_EN;
                case 3:
                    return DUID_LL;
                default:
                    throw new IllegalArgumentException("Unknown type: " + type);
            }
        }
    }
    // general field
    private DuidType duidType;

    // fields for DUID_LLT & DUID_LL
    private short hardwareType;
    private int duidTime;
    private byte[] linkLayerAddress;

    // fields for DUID_EN
    private int enterpriseNumber;
    private byte[] identifier;

    public DuidType getDuidType() {
        return duidType;
    }

    public void setDuidType(DuidType duidType) {
        this.duidType = duidType;
    }

    public short getHardwareType() {
        return hardwareType;
    }

    public void setHardwareType(short hardwareType) {
        this.hardwareType = hardwareType;
    }

    public int getDuidTime() {
        return duidTime;
    }

    public void setDuidTime(int duidTime) {
        this.duidTime = duidTime;
    }

    public byte[] getLinkLayerAddress() {
        return linkLayerAddress;
    }

    public void setLinkLayerAddress(byte[] linkLayerAddress) {
        this.linkLayerAddress = linkLayerAddress;
    }

    public int getEnterpriseNumber() {
        return enterpriseNumber;
    }

    public void setEnterpriseNumber(int enterpriseNumber) {
        this.enterpriseNumber = enterpriseNumber;
    }

    public byte[] getIdentifier() {
        return identifier;
    }

    public void setIdentifier(byte[] identifier) {
        this.identifier = identifier;
    }

    @Override
    public byte[] serialize() {
        ByteBuffer byteBuffer;
        switch (duidType) {
            case DUID_LLT:
                byteBuffer = ByteBuffer.allocate(DEFAULT_LLT_LEN + linkLayerAddress.length);
                byteBuffer.putShort(duidType.value);
                byteBuffer.putShort(hardwareType);
                byteBuffer.putInt(duidTime);
                byteBuffer.put(linkLayerAddress);
                break;
            case DUID_EN:
                byteBuffer = ByteBuffer.allocate(DEFAULT_EN_LEN + identifier.length);
                byteBuffer.putShort(duidType.value);
                byteBuffer.putInt(enterpriseNumber);
                byteBuffer.put(identifier);
                break;
            case DUID_LL:
                byteBuffer = ByteBuffer.allocate(DEFAULT_LL_LEN + linkLayerAddress.length);
                byteBuffer.putShort(duidType.value);
                byteBuffer.putShort(hardwareType);
                byteBuffer.put(linkLayerAddress);
                break;
            default:
                throw new IllegalArgumentException("Unknown duidType: " + duidType.toString());
        }
        return byteBuffer.array();
    }



    public static Deserializer<Dhcp6Duid> deserializer() {
        return (data, offset, length) -> {
            Dhcp6Duid duid = new Dhcp6Duid();
            ByteBuffer byteBuffer = ByteBuffer.wrap(data, offset, length);

            DuidType duidType = DuidType.of(byteBuffer.getShort());
            duid.setDuidType(duidType);
            switch (duidType) {
                case DUID_LLT:
                    duid.setHardwareType(byteBuffer.getShort());
                    duid.setDuidTime(byteBuffer.getInt());
                    duid.linkLayerAddress = new byte[length - DEFAULT_LLT_LEN];
                    byteBuffer.get(duid.linkLayerAddress);
                    break;
                case DUID_EN:
                    duid.setEnterpriseNumber(byteBuffer.getInt());
                    duid.identifier = new byte[length - DEFAULT_EN_LEN];
                    byteBuffer.get(duid.identifier);
                    break;
                case DUID_LL:
                    duid.setHardwareType(byteBuffer.getShort());
                    duid.linkLayerAddress = new byte[length - DEFAULT_LL_LEN];
                    byteBuffer.get(duid.linkLayerAddress);
                    break;
                default:
                    throw new IllegalArgumentException("Unknown type: " + duidType);
            }
            return duid;
        };
    }

    @Override
    public String toString() {
        MoreObjects.ToStringHelper helper = MoreObjects.toStringHelper(getClass());

        switch (duidType) {
            case DUID_LLT:
                helper.add("type", "DUID_LLT");
                helper.add("hardwareType", hardwareType);
                helper.add("duidTime", duidTime);
                helper.add("linkLayerAddress", Arrays.toString(linkLayerAddress));
                break;
            case DUID_EN:
                helper.add("type", "DUID_EN");
                helper.add("enterpriseNumber", enterpriseNumber);
                helper.add("id", Arrays.toString(identifier));
                break;
            case DUID_LL:
                helper.add("type", "DUID_LL");
                helper.add("hardwareType", hardwareType);
                helper.add("linkLayerAddress", Arrays.toString(linkLayerAddress));
                break;
            default:
                helper.add("type", "Unknown");
        }
        return helper.toString();
    }
}
