package ru.rsdn.patterns.behavioral.observer;

import java.lang.ref.WeakReference;
import java.util.Collection;
import java.util.HashSet;
import java.util.concurrent.CopyOnWriteArrayList;

/**
 * Издатель, использующий слабую связь с подписчиками
 * @param <S> тип подписчика
 */
public abstract class Publisher<S> {
	private final Collection<WeakReference<S>> subscribers = new CopyOnWriteArrayList<WeakReference<S>>();

	/**
	 * Подписаться
	 * @param subscriber подписчик
	 */
	public void subscribe(S subscriber) {
		if (subscriber == null)
			throw new NullPointerException("Пустой параметр");
		subscribers.add(new WeakReference<S>(subscriber));
	}

	/**
	 * Отписаться
	 * @param subscriber подписчик
	 */
	public void unsubscribe(S subscriber) {
		if (subscriber == null)
			throw new NullPointerException("Пустой параметр");
		for (final WeakReference<S> ref : subscribers) {
			final S _subscriber = ref.get();
			if (_subscriber == null || _subscriber == subscriber)
				subscribers.remove(ref);
		}
	}

	/**
	 * @return подписчики
	 */
	protected Collection<S> getSubscribers() {
		final Collection<S> result = new HashSet<S>();
		for (final WeakReference<S> ref : subscribers) {
			final S subscriber = ref.get();
			if (subscriber == null)
				subscribers.remove(ref);
			else
				result.add(subscriber);
		}
		return result;
	}
}
