/*
 * 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.ov.mixing.proofs.bg.state;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 * Implementation of a {@link StateHarvester} as a {@link ConcurrentHashMap}.
 */
public class MapBasedHarvester implements StateHarvester {

    private static final Logger LOG = Logger.getLogger(MapBasedHarvester.class.getName());

    private final Map<StateLabel, Object> state = new ConcurrentHashMap<>();

    /**
     * @see StateHarvester#collect(StateHarvester.State, java.lang.Object)
     */
    @Override
    public void collect(final StateLabel label, final Object object) {
        this.state.put(label, object);
    }

    /**
     * This implementation also accepts the associated object being a {@link Future}.<br>
     * In that case, instead of the Future itself, the result of calling the {@link Future#get()} method is returned
     * (note that this will block the calling thread until the value is available)<br>
     * 
     * @see StateHarvester#offer(StateLabel, java.lang.Class)
     */
    @Override
    public <T> T offer(final StateLabel label, final Class<T> clazz) {

        Object ret = state.get(label);
        if (ret instanceof Future<?>) {

            try {
                ret = ((Future<?>) ret).get();

            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
                LOG.log(Level.SEVERE, "Problems retrieving value for calculation " + label, e);
                throw new IllegalStateException("Failed to offer value.", e);

            } catch (ExecutionException e) {
                LOG.log(Level.SEVERE, "Problems retrieving value for calculation " + label, e);
                throw new IllegalStateException("Failed to offer value.", e);
            }
        }
        return clazz.cast(ret);
    }
}
