/*
 * Copyright 2018 Scytl Secure Electronic Voting SA
 *
 * All rights reserved
 *
 * See our extended copyright notice in *file 'Copyright.txt' which is part of this source code package
 */
package com.scytl.products.ov.commons.dto;

import static com.scytl.products.ov.commons.safestream.StreamSerializableUtil.retrieveStringValueWithNullCheck;
import static com.scytl.products.ov.commons.safestream.StreamSerializableUtil.storeStringValueWithNullCheck;

import java.io.IOException;
import java.util.UUID;

import org.msgpack.core.MessagePacker;
import org.msgpack.core.MessageUnpacker;

import com.scytl.products.ov.commons.beans.domain.model.messaging.SafeStreamDeserializationException;
import com.scytl.products.ov.commons.beans.domain.model.messaging.StreamSerializable;
import com.scytl.products.ov.commons.beans.domain.model.messaging.StreamSerializableClassType;
import com.scytl.products.ov.commons.safestream.StreamSerializableUtil;

public class ChoiceCodeGenerationDTO<T> extends CorrelatedSupport implements StreamSerializable {

    private String requestId;

    private T payload;
    
    public ChoiceCodeGenerationDTO() {
        super();
    }

    public ChoiceCodeGenerationDTO(UUID correlationId, String requestId, T payload) {
        super(correlationId);
        this.requestId = requestId;
        this.payload = payload;
    }

    public String getRequestId() {
        return requestId;
    }

    public void setRequestId(String requestId) {
        this.requestId = requestId;
    }

    public T getPayload() {
        return payload;
    }

    public void setPayload(T payload) {
        this.payload = payload;
    }

    @Override
    public void serialize(MessagePacker packer) throws IOException {
        storeStringValueWithNullCheck(packer, getCorrelationId().toString());
        packer.packString(requestId);
        if(payload instanceof StreamSerializable) {
            packer.packString(((StreamSerializable) payload).type().name());
            ((StreamSerializable) payload).serialize(packer);
        } else if(payload instanceof String) {
            packer.packString(String.class.getName());
            storeStringValueWithNullCheck(packer, (String) payload);
        } else {
            throw new IOException(payload.getClass().getName() + " type is not supported");
        }
    }

    @SuppressWarnings("unchecked")
    @Override
    public void deserialize(MessageUnpacker unpacker) throws SafeStreamDeserializationException {
        try {
            setCorrelationId(UUID.fromString(retrieveStringValueWithNullCheck(unpacker)));
            this.requestId = unpacker.unpackString();
            String unpackString = unpacker.unpackString();
            if(String.class.getName().equals(unpackString)) {
                payload = (T) unpacker.unpackString();
            } else {
                StreamSerializable resolveByName = (StreamSerializable) StreamSerializableUtil.resolveByName(unpackString);
                resolveByName.deserialize(unpacker);
                payload = (T) resolveByName;
            }
        } catch (IOException e) {
            throw new SafeStreamDeserializationException(e);
        }
    }

    @Override
    public StreamSerializableClassType type() {
        return StreamSerializableClassType.CHOICE_CODE_GENERATION_DTO;
    }
}
