/*
 * Copyright Avaya Inc., All Rights Reserved.
 *
 * THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF Avaya Inc.
 *
 * The copyright notice above does not evidence any actual or intended
 * publication of such source code.
 *
 * Some third-party source code components may have been modified from their
 * original versions by Avaya Inc.
 *
 * The modifications are Copyright Avaya Inc., All Rights Reserved.
 */

package com.avaya.oceanalytics.openinterface.websocketclient.subscription;

import org.springframework.beans.factory.DisposableBean;
import org.springframework.stereotype.Component;

import java.util.Collections;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.atomic.AtomicBoolean;

/**
 * Repository for active subscriptions.
 *
 * @author seprokof
 *
 */
@Component
public class SubscriptionManager implements DisposableBean {

    private final ConcurrentMap<String, Subscription> subscriptionByProducer = new ConcurrentHashMap<>();
    private final AtomicBoolean isDestroying = new AtomicBoolean(false);

    /**
     * Associates a subscription with a specific producer id.
     *
     * @param producerId
     *            the unique identifier of producer
     * @param subscription
     *            the instance of subscription to be associated with particular producer id
     */
    public void associate(String producerId, Subscription subscription) {
        checkState();
        subscriptionByProducer.put(producerId, subscription);
    }

    /**
     * Retrieves subscription associated with given producer id.
     *
     * @param producerId
     *            the unique identifier of producer
     * @return associated subscription or <code>null</code> if manager contains no subscription for that producer id
     */
    public Subscription getSubscription(String producerId) {
        return subscriptionByProducer.get(producerId);
    }

    /**
     * Dissociates a subscription for a specific producer id.
     *
     * @param producerId
     *            the unique identifier of producer
     * @return dissociated subscription or <code>null</code> if manager contains no subscription for that producer id
     */
    public Subscription dissociate(String producerId) {
        checkState();
        return subscriptionByProducer.remove(producerId);
    }

    /**
     * Provides read-only view of all active producer id subscriptions.
     *
     * @return an unmodifiable view of all active producer id subscriptions
     */
    public Set<String> getAllSubscriptions() {
        return Collections.unmodifiableSet(subscriptionByProducer.keySet());
    }

    @Override
    public void destroy() {
        isDestroying.set(true);
        subscriptionByProducer.values().forEach(s->s.getRtdDataProvider().disconnect());
        subscriptionByProducer.clear();
    }

    private void checkState() {
        if (isDestroying.get()) {
            throw new IllegalStateException("Subscription manager shutted down");
        }
    }
}
