/*
 * Copyright (c) 2019 the Eclipse Milo Authors
 *
 * This program and the accompanying materials are made
 * available under the terms of the Eclipse Public License 2.0
 * which is available at https://www.eclipse.org/legal/epl-2.0/
 *
 * SPDX-License-Identifier: EPL-2.0
 */

package org.eclipse.milo.opcua.stack.core.channel.headers;

import io.netty.buffer.ByteBuf;
import org.eclipse.milo.opcua.stack.core.UaException;
import org.eclipse.milo.opcua.stack.core.channel.messages.MessageType;

public final class SecureMessageHeader {

    public static final int SECURE_MESSAGE_HEADER_SIZE = 12;

    private final MessageType messageType;
    private final char finalFlag;
    private final long messageSize;
    private final long secureChannelId;

    /**
     * @param messageType     the {@link MessageType} of the following message.
     * @param finalFlag       a one byte ASCII code that indicates whether the MessageChunk is the final chunk in a
     *                        Message. The following values are defined at this time: 'C', an intermediate chunk, 'F',
     *                        the final chunk, and  'A', the final chunk (used when an error occurred and the Message
     *                        is aborted).
     * @param messageSize     the length of the MessageChunk, in bytes. This value includes size of the Message header.
     * @param secureChannelId a unique identifier for the SecureChannel assigned by the Server.
     */
    public SecureMessageHeader(MessageType messageType, char finalFlag, long messageSize, long secureChannelId) {
        this.messageType = messageType;
        this.finalFlag = finalFlag;
        this.messageSize = messageSize;
        this.secureChannelId = secureChannelId;
    }

    public MessageType getMessageType() {
        return messageType;
    }

    public char getChunkType() {
        return finalFlag;
    }

    public long getMessageSize() {
        return messageSize;
    }

    public long getSecureChannelId() {
        return secureChannelId;
    }

    public static void encode(SecureMessageHeader header, ByteBuf buffer) throws UaException {
        buffer.writeMediumLE(MessageType.toMediumInt(header.getMessageType()));
        buffer.writeByte(header.getChunkType());
        buffer.writeIntLE((int) header.getMessageSize());
        buffer.writeIntLE((int) header.getSecureChannelId());
    }

    public static SecureMessageHeader decode(ByteBuf buffer) throws UaException {
        return new SecureMessageHeader(
            MessageType.fromMediumInt(buffer.readMediumLE()),
            (char) buffer.readByte(),
            buffer.readUnsignedIntLE(),
            buffer.readUnsignedIntLE()
        );
    }

}
