package ru.rsdn.patterns.behavioral.observer.problems.thread;

import java.util.List;

import org.junit.Assert;

import ru.rsdn.patterns.behavioral.observer.ISubscriber;
import ru.rsdn.patterns.behavioral.observer.AbstractPublisher;
import ru.rsdn.patterns.behavioral.observer.Subscriber;

/**
 * Тестирование абстрактного издателя
 * @param <T> тип списка подписчиков
 */
public class AbstractPublisherTest<T extends List<ISubscriber>> extends
		AbstractPublisher<T> {
	protected final ISubscriber subscriber = new Subscriber();

	/**
	 * Конструктор
	 * @param _subscribers список подписчиков
	 */
	public AbstractPublisherTest(T _subscribers) {
		super(_subscribers);
	}

	/**
	 * Небезопасное оповещение подписчиков на основе перебора списка циклом
	 */
	public void unsafeNotifyByCycle() {
		subscribe(subscriber);
		unsafeNotifyByCycle(subscribers);
	}

	protected void unsafeNotifyByCycle(T _subscribers) {
		for (int i = 0; i < _subscribers.size(); i++) {
			if (i == _subscribers.size() - 1)
				invokeTrouble();
			_subscribers.get(i).eventHappen();
		}
	}

	/**
	 * Небезопасное оповещение подписчиков на основе перебора с использованием
	 * java.util.Iterator
	 */
	public void unsafeNotifyByIterator() {
		subscribe(subscriber);
		for (final ISubscriber _subscriber : subscribers) {
			invokeTrouble();
			_subscriber.eventHappen();
		}
	}

	/**
	 * Имитировать проблему
	 */
	protected void invokeTrouble() {
		new Thread(new Runnable() {
			public void run() {
				unsubscribe(subscriber);
			}
		}).start();
		try {
			Thread.sleep(1000);
		} catch (final InterruptedException e) {
			Assert.fail();
		}
	}
}
