/*
 * 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 com.scytl.products.ov.commons.beans.domain.model.messaging.SafeStreamDeserializationException;
import static com.scytl.products.ov.commons.safestream.StreamSerializableUtil.*;

import java.io.IOException;
import java.time.ZonedDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;

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

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

public class KeyCreationDTO extends CorrelatedSupport implements StreamSerializable, WithDTOResultsKeyFields {

    private String requestId;

    private String signature;

    private String resourceId;

    private String encryptionParameters;

    private String electionEventId;

    private ZonedDateTime from;

    private ZonedDateTime to;

    private List<CCPublicKey> publicKeys;

    public KeyCreationDTO() {
        super();
    }

    public KeyCreationDTO(KeyCreationDTO data) {
        super(data.getCorrelationId());
        this.requestId = data.requestId;
        this.resourceId = data.resourceId;
        this.encryptionParameters = data.encryptionParameters;
        this.electionEventId = data.electionEventId;
        this.from = data.from;
        this.to = data.to;
    }

    public String getElectionEventId() {
        return electionEventId;
    }

    public void setElectionEventId(String electionEventId) {
        this.electionEventId = electionEventId;
    }

    public String getRequestId() {
        return requestId;
    }

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

    public String getSignature() {
        return signature;
    }

    public void setSignature(String signature) {
        this.signature = signature;
    }

    public String getResourceId() {
        return resourceId;
    }

    public void setResourceId(String resourceId) {
        this.resourceId = resourceId;
    }

    public String getEncryptionParameters() {
        return encryptionParameters;
    }

    public void setEncryptionParameters(String encryptionParameters) {
        this.encryptionParameters = encryptionParameters;
    }

    public List<CCPublicKey> getPublicKeys() {
        return publicKeys;
    }

    public void setPublicKey(List<CCPublicKey> publicKeys) {
        this.publicKeys = publicKeys;
    }

    public ZonedDateTime getFrom() {
        return from;
    }

    public void setFrom(ZonedDateTime from) {
        this.from = from;
    }

    public ZonedDateTime getTo() {
        return to;
    }

    public void setTo(ZonedDateTime to) {
        this.to = to;
    }

    @Override
    public String[] getResultsKeyFields() {
        return new String[] {getElectionEventId(), getResourceId(), getRequestId() };
    }

    @Override
    public void serialize(MessagePacker packer) throws IOException {
        storeStringValueWithNullCheck(packer, getCorrelationId().toString());
        storeStringValueWithNullCheck(packer, requestId);
        storeStringValueWithNullCheck(packer, signature);
        storeStringValueWithNullCheck(packer, resourceId);
        storeStringValueWithNullCheck(packer, encryptionParameters);
        storeStringValueWithNullCheck(packer, electionEventId);

        storeDateValueWithNullCheck(packer, from);
        storeDateValueWithNullCheck(packer, to);
        
        if(publicKeys != null) {
            packer.packArrayHeader(publicKeys.size());
            for (CCPublicKey ccPublicKey : publicKeys) {
                ccPublicKey.serialize(packer);
            }
        } else {
            packer.packNil();
        }
    }

    @Override
    public void deserialize(MessageUnpacker unpacker) throws SafeStreamDeserializationException {
        try {
            setCorrelationId(UUID.fromString(retrieveStringValueWithNullCheck(unpacker)));
            this.requestId = retrieveStringValueWithNullCheck(unpacker);
            this.signature = retrieveStringValueWithNullCheck(unpacker);
            this.resourceId = retrieveStringValueWithNullCheck(unpacker);
            this.encryptionParameters = retrieveStringValueWithNullCheck(unpacker);
            this.electionEventId = retrieveStringValueWithNullCheck(unpacker);
            this.from = retrieveDateValueWithNullCheck(unpacker);
            this.to = retrieveDateValueWithNullCheck(unpacker);
            if(!unpacker.tryUnpackNil()) {
                int listSize = unpacker.unpackArrayHeader();
                this.publicKeys = new ArrayList<>(listSize);
                for (int i = 0; i < listSize; i++) {
                    CCPublicKey key = new CCPublicKey();
                    key.deserialize(unpacker);
                    publicKeys.add(key);
                }
            } else {
                publicKeys = null;
            }
        } catch (IOException e) {
            throw new SafeStreamDeserializationException(e);
        }
    }

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