package eu.dnetlib.server;

import java.io.Serializable;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.Date;
import java.util.Iterator;
import java.util.Map.Entry;
import java.util.concurrent.ConcurrentHashMap;
import java.util.logging.Logger;

import eu.dnetlib.client.shared.Data;
import eu.dnetlib.efg1914.authoring.components.Configuration;
import eu.dnetlib.efg1914.authoring.components.Frame;
import eu.dnetlib.efg1914.authoring.components.Item;
import eu.dnetlib.efg1914.authoring.components.Theme;
import eu.dnetlib.efg1914.authoring.components.Topic;
import eu.dnetlib.efg1914.authoring.users.User;

public class ComponentsRegistry implements Serializable, NotificationRegistry {
	/**
	 * 
	 */
	private static Logger log = Logger.getLogger("ComponentsRegistry.java");
	private static final long serialVersionUID = 1L;
	private ConcurrentHashMap<Date, Item> newItems;
	private ConcurrentHashMap<Date, Item> updatedItems;

	private ConcurrentHashMap<Date, Item> deletedItems;

	private ConcurrentHashMap<Date, Frame> newFrames;
	private ConcurrentHashMap<Date, Frame> deletedFrames;

	private ConcurrentHashMap<String, Date> registeredUsers;
	private Date updateNumber;

	private ConcurrentHashMap<Date, Frame> updatedFrames;

	private ConcurrentHashMap<Date, Topic> newTopics;

	private ConcurrentHashMap<Date, Theme> newThemes;

	private ConcurrentHashMap<Date, Topic> deletedTopics;

	private ConcurrentHashMap<Date, Topic> updatedTopics;

	private ConcurrentHashMap<Date, Theme> deletedThemes;

	private ConcurrentHashMap<Date, Theme> updatedThemes;

	private ConcurrentHashMap<String, Date> activeComponentsLog;

	private ConcurrentHashMap<String, String> activeComponents;

	private ConcurrentHashMap<Date, User> newUsers;
	private ConcurrentHashMap<Date, User> updatedUsers;
	// string user id
	private ConcurrentHashMap<Date, String> deletedUsers;
	private Configuration configuration = null;
	private Date configurationDate = null;

	public ComponentsRegistry() {
		Date date = new Date();
		updateNumber = new Timestamp(date.getTime());
		this.deletedItems = new ConcurrentHashMap<Date, Item>();
		this.newItems = new ConcurrentHashMap<Date, Item>();
		this.updatedItems = new ConcurrentHashMap<Date, Item>();

		this.deletedFrames = new ConcurrentHashMap<Date, Frame>();
		this.newFrames = new ConcurrentHashMap<Date, Frame>();
		this.updatedFrames = new ConcurrentHashMap<Date, Frame>();

		this.deletedTopics = new ConcurrentHashMap<Date, Topic>();
		this.updatedTopics = new ConcurrentHashMap<Date, Topic>();
		this.newTopics = new ConcurrentHashMap<Date, Topic>();

		this.updatedThemes = new ConcurrentHashMap<Date, Theme>();
		this.deletedThemes = new ConcurrentHashMap<Date, Theme>();
		this.newThemes = new ConcurrentHashMap<Date, Theme>();

		this.registeredUsers = new ConcurrentHashMap<String, Date>();
		this.activeComponents = new ConcurrentHashMap<String, String>();
		this.activeComponentsLog = new ConcurrentHashMap<String, Date>();

		this.deletedUsers = new ConcurrentHashMap<Date, String>();
		this.newUsers = new ConcurrentHashMap<Date, User>();
		this.updatedUsers = new ConcurrentHashMap<Date, User>();
		this.configuration = null;
		configurationDate = null;
	}

	// ITEMS
	//
	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * eu.dnetlib.server.NotificationRegistry#addItem(eu.dnetlib.efg1914.authoring
	 * .components.Item)
	 */
	public void addItem(Item it) {

		Date date = new Date();
		if (it != null) {
			Timestamp t = new Timestamp(date.getTime());
			log.info("\n\n+++++++++++++++++ added  new item at " + t);
			this.newItems.put(t, it);
		}
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * eu.dnetlib.server.NotificationRegistry#addDeletedItem(eu.dnetlib.efg1914
	 * .authoring.components.Item)
	 */
	public void addDeletedItem(Item id) {

		Date date = new Date();
		if (id != null) {
			log.info("\n\n+++++++++++++++++ added  deleted item at " + id);
			this.deletedItems.put(new Timestamp(date.getTime()), id);
			// TODO remove from active
			unmarkComponent(id.getId());
		}
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * eu.dnetlib.server.NotificationRegistry#addUpdatedItem(eu.dnetlib.efg1914
	 * .authoring.components.Item)
	 */
	public void addUpdatedItem(Item it) {

		Date date = new Date();
		if (it != null) {
			log.info("\n\n+++++++++++++++++ added  update item at " + it.toString());
			this.updatedItems.put(new Timestamp(date.getTime()), it);

		}
	}

	// FRAMES
	//
	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * eu.dnetlib.server.NotificationRegistry#addFrame(eu.dnetlib.efg1914.authoring
	 * .components.Frame)
	 */
	public void addFrame(Frame it) {
		Date date = new Date();
		if (it != null) {
			this.newFrames.put(new Timestamp(date.getTime()), it);
		}
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * eu.dnetlib.server.NotificationRegistry#addUpdatedFrame(eu.dnetlib.efg1914
	 * .authoring.components.Frame)
	 */
	public void addUpdatedFrame(Frame it) {
		Date date = new Date();
		if (it != null) {
			this.updatedFrames.put(new Timestamp(date.getTime()), it);
		}
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * eu.dnetlib.server.NotificationRegistry#addDeletedFrame(eu.dnetlib.efg1914
	 * .authoring.components.Frame)
	 */
	public void addDeletedFrame(Frame id) {
		Date date = new Date();

		if (id != null) {
			this.deletedFrames.put(new Timestamp(date.getTime()), id);
			// TODO remove from active
			unmarkComponent(id.getId());
		}
	}

	// TOPICS
	//
	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * eu.dnetlib.server.NotificationRegistry#addTopic(eu.dnetlib.efg1914.authoring
	 * .components.Topic)
	 */
	public void addTopic(Topic it) {
		Date date = new Date();
		if (it != null) {
			this.newTopics.put(new Timestamp(date.getTime()), it);
		}
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * eu.dnetlib.server.NotificationRegistry#addDeletedTopic(eu.dnetlib.efg1914
	 * .authoring.components.Topic)
	 */
	public void addDeletedTopic(Topic id) {
		Date date = new Date();
		if (id != null) {
			this.deletedTopics.put(new Timestamp(date.getTime()), id);
			// TODO remove from active
			unmarkComponent(id.getId());
		}
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * eu.dnetlib.server.NotificationRegistry#addUpdatedTopic(eu.dnetlib.efg1914
	 * .authoring.components.Topic)
	 */
	public void addUpdatedTopic(Topic it) {

		Date date = new Date();
		if (it != null) {
			this.updatedTopics.put(new Timestamp(date.getTime()), it);
		}
	}

	// THEMES

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * eu.dnetlib.server.NotificationRegistry#addTheme(eu.dnetlib.efg1914.authoring
	 * .components.Theme)
	 */
	public void addTheme(Theme it) {
		Date date = new Date();
		if (it != null) {
			this.newThemes.put(new Timestamp(date.getTime()), it);
		}
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * eu.dnetlib.server.NotificationRegistry#addDeletedTheme(eu.dnetlib.efg1914
	 * .authoring.components.Theme)
	 */
	public void addDeletedTheme(Theme id) {
		Date date = new Date();
		if (id != null) {
			this.deletedThemes.put(new Timestamp(date.getTime()), id);
			// TODO remove from active
			unmarkComponent(id.getId());
		}
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * eu.dnetlib.server.NotificationRegistry#addUpdatedTheme(eu.dnetlib.efg1914
	 * .authoring.components.Theme)
	 */
	public void addUpdatedTheme(Theme it) {
		Date date = new Date();
		if (it != null) {
			this.updatedThemes.put(new Timestamp(date.getTime()), it);
		}
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see eu.dnetlib.server.NotificationRegistry#destroy()
	 */
	public void destroy() {
		this.deletedItems.clear();
		this.newItems.clear();

		this.updatedItems.clear();

		this.deletedFrames.clear();
		this.newFrames.clear();
		this.updatedFrames.clear();

		this.deletedTopics.clear();
		this.updatedTopics.clear();
		this.newTopics.clear();

		this.updatedThemes.clear();
		this.deletedThemes.clear();
		this.newThemes.clear();
		this.activeComponents.clear();

		this.deletedUsers.clear();
		this.newUsers.clear();
		this.updatedUsers.clear();
		this.configuration = null;
		this.configurationDate = null;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * eu.dnetlib.server.NotificationRegistry#markComponent(java.lang.String,
	 * java.lang.String)
	 */
	public void markComponent(String componentId, String userId) {
		if (componentId != null && (!this.getActiveComponents().containsKey(componentId))) {

			this.getActiveComponents().put(componentId, userId);
			Date date = new Date();
			this.activeComponentsLog.put(componentId, new Timestamp(date.getTime()));
		}
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * eu.dnetlib.server.NotificationRegistry#unmarkComponent(java.lang.String,
	 * java.lang.String)
	 */
	public void unmarkComponent(String componentId, String userId) {

		if (componentId != null && !this.getActiveComponents().isEmpty() && this.getActiveComponents().containsKey(componentId)) {

			String user = this.getActiveComponents().get(componentId);
			if (userId != null && userId.equals(user)) {
				this.getActiveComponents().remove(componentId);

				this.getActiveComponentsLog().remove(componentId);
			}
		}
	}

	public void unmarkComponent(String componentId) {

		if ((componentId != null) && (this.getActiveComponents() != null) && (!this.getActiveComponents().isEmpty()) && (this.getActiveComponents().containsKey(componentId))) {
			this.getActiveComponents().remove(componentId);
			this.getActiveComponentsLog().remove(componentId);
		}
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see eu.dnetlib.server.NotificationRegistry#clearUpCache()
	 */
	public synchronized void clearUpCache() {

		Timestamp updateThreshold = new Timestamp((long) (System.currentTimeMillis() - 360000 * 1000));

		Timestamp activeComponentsThreshold = new Timestamp((long) (System.currentTimeMillis() - 3600 * 1000));
		// clear components that have been marked as active for over an hour

		{
			Iterator<Entry<Date, Item>> iterator = this.newItems.entrySet().iterator();
			while (iterator.hasNext()) {
				Entry<Date, Item> entry = iterator.next();
				if (entry.getKey().before(updateThreshold)) {

					this.newItems.remove(entry.getKey());
					log.info("clearing up  items cache ....");
				}

			}

		}

		// synchronized (newFrames)
		{
			Iterator<Entry<Date, Frame>> iterator = this.newFrames.entrySet().iterator();
			while (iterator.hasNext()) {
				Entry<Date, Frame> entry = iterator.next();
				if (entry.getKey().before(updateThreshold)) {

					this.newFrames.remove(entry.getKey());
					log.info("clearing up  frames cache ....");

				}

			}
		}

		// synchronized (newTopics)
		{
			Iterator<Entry<Date, Topic>> iterator = this.newTopics.entrySet().iterator();
			while (iterator.hasNext()) {
				Entry<Date, Topic> entry = iterator.next();
				if (entry.getKey().before(updateThreshold)) {

					this.newTopics.remove(entry.getKey());
					log.info("clearing up  topics cache ....");
				}

			}
		}

		{
			Iterator<Entry<Date, Theme>> iterator = this.newThemes.entrySet().iterator();

			while (iterator.hasNext()) {
				Entry<Date, Theme> entry = iterator.next();
				if (entry.getKey().before(updateThreshold)) {

					this.newThemes.remove(entry.getKey());
					log.info("clearing up  themes cache ....");
				}

			}

		}

		{
			Iterator<Entry<Date, Item>> iterator = this.deletedItems.entrySet().iterator();

			while (iterator.hasNext()) {

				Entry<Date, Item> entry = iterator.next();
				if (entry.getKey().before(updateThreshold)) {

					this.deletedItems.remove(entry.getKey());
					log.info("clearing up  deleted items cache ....");

				}

			}
		}

		// synchronized (deletedFrames)
		{
			Iterator<Entry<Date, Frame>> iteratorS = this.deletedFrames.entrySet().iterator();
			while (iteratorS.hasNext()) {

				Entry<Date, Frame> entry = iteratorS.next();
				if (entry.getKey().before(updateThreshold)) {

					this.deletedFrames.remove(entry.getKey());
					log.info("clearing up  deleted frames cache ....");

				}
			}
		}

		{
			Iterator<Entry<Date, Topic>> iteratorS = this.deletedTopics.entrySet().iterator();
			while (iteratorS.hasNext()) {
				Entry<Date, Topic> entry = iteratorS.next();
				if (entry.getKey().before(updateThreshold)) {

					this.deletedTopics.remove(entry.getKey());
					log.info("clearing up  deleted topics cache ....");
				}

			}
		}
		{

			Iterator<Entry<Date, Theme>> iterator = this.deletedThemes.entrySet().iterator();
			while (iterator.hasNext()) {
				Entry<Date, Theme> entry = iterator.next();
				if (entry.getKey().before(updateThreshold)) {

					this.deletedThemes.remove(entry.getKey());
					log.info("clearing up  deleted themes cache ....");
				}

			}
		}

		{
			Iterator<Entry<Date, Item>> iterator = this.updatedItems.entrySet().iterator();
			while (iterator.hasNext()) {
				Entry<Date, Item> entry = iterator.next();
				if (entry.getKey().before(updateThreshold)) {

					this.updatedItems.remove(entry.getKey());
					log.info("clearing up  updated items cache ....");
				}

			}
		}

		// synchronized (updatedFrames)
		{
			Iterator<Entry<Date, Frame>> iterator = this.updatedFrames.entrySet().iterator();
			while (iterator.hasNext()) {
				Entry<Date, Frame> entry = iterator.next();
				if (entry.getKey().before(updateThreshold)) {

					this.updatedFrames.remove(entry.getKey());
					log.info("clearing up  updated frames cache ....");
				}

			}
		}

		{
			Iterator<Entry<Date, Topic>> iterator = this.updatedTopics.entrySet().iterator();
			while (iterator.hasNext()) {
				Entry<Date, Topic> entry = iterator.next();
				if (entry.getKey().before(updateThreshold)) {

					this.updatedTopics.remove(entry.getKey());
					log.info("clearing up  updated topics cache ....");
				}

			}
		}

		{

			Iterator<Entry<Date, Theme>> iterator = this.updatedThemes.entrySet().iterator();
			while (iterator.hasNext()) {
				Entry<Date, Theme> entry = iterator.next();

				if (entry.getKey().before(updateThreshold)) {

					this.updatedThemes.remove(entry.getKey());
					log.info("clearing up  updated themes cache ....");
				}

			}
		}

		{
			Iterator<Entry<String, Date>> iteratorA = this.activeComponentsLog.entrySet().iterator();
			while (iteratorA.hasNext()) {
				Entry<String, Date> entry = iteratorA.next();

				if (entry.getValue().before(activeComponentsThreshold)) {
					log.info("clearing active....");

					this.activeComponents.remove(entry.getKey());

					this.activeComponentsLog.remove(entry.getKey());
				}

			}

		}
		{
			Iterator<Entry<Date, User>> iterator = this.newUsers.entrySet().iterator();
			while (iterator.hasNext()) {
				Entry<Date, User> entry = iterator.next();
				if (entry.getKey().before(updateThreshold)) {

					this.newUsers.remove(entry.getKey());
					log.info("clearing up  Users cache ....");
				}

			}

		}
		{
			Iterator<Entry<Date, String>> iterator = this.deletedUsers.entrySet().iterator();

			while (iterator.hasNext()) {

				Entry<Date, String> entry = iterator.next();
				if (entry.getKey().before(updateThreshold)) {

					this.deletedUsers.remove(entry.getKey());
					log.info("clearing up  deleted Users cache ....");

				}

			}
		}
		{
			Iterator<Entry<Date, User>> iterator = this.updatedUsers.entrySet().iterator();
			while (iterator.hasNext()) {
				Entry<Date, User> entry = iterator.next();
				if (entry.getKey().before(updateThreshold)) {

					this.updatedUsers.remove(entry.getKey());
					log.info("clearing up  updated Users cache ....");
				}

			}
		}
		if (this.configurationDate != null && this.configurationDate.before(updateThreshold)) {
			this.configuration = null;
			this.configurationDate = null;
			log.info("clearing up  configuration cache ....");
		}
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * eu.dnetlib.server.NotificationRegistry#receiveUpdates(java.lang.String)
	 */
	public Data receiveUpdates(String user) {
		Data data = new Data();
		Date lastUpdateTime = this.registeredUsers.get(user);

		Date newLastUpdateTime = lastUpdateTime;

		if (configuration != null) {
			if (configurationDate != null && configurationDate.after(lastUpdateTime)) {
				data.setConfiguration(configuration);
				newLastUpdateTime = configurationDate;
			} else {
				data.setConfiguration(null);
			}
		} else {
			data.setConfiguration(null);
		}

		if (!this.newItems.isEmpty()) {
			Iterator<Entry<Date, Item>> iterator = this.newItems.entrySet().iterator();
			while (iterator.hasNext()) {

				Entry<Date, Item> entry = iterator.next();
				if (entry.getKey().after(lastUpdateTime)) {
					data.getNewItems().add(entry.getValue());
					if (entry.getKey().after(newLastUpdateTime)) {
						newLastUpdateTime = entry.getKey();
					}

				}

			}
		}
		if (!this.newFrames.isEmpty()) {
			Iterator<Entry<Date, Frame>> iterator = this.newFrames.entrySet().iterator();
			while (iterator.hasNext()) {
				Entry<Date, Frame> entry = iterator.next();
				if (entry.getKey().after(lastUpdateTime))

				{
					data.getNewFrames().add(entry.getValue());
					if (entry.getKey().after(newLastUpdateTime)) {
						newLastUpdateTime = entry.getKey();
					}

				}

			}
		}

		if (!this.newTopics.isEmpty()) {
			Iterator<Entry<Date, Topic>> iterator = this.newTopics.entrySet().iterator();
			while (iterator.hasNext()) {
				Entry<Date, Topic> entry = iterator.next();
				if (entry.getKey().after(lastUpdateTime))

				{

					data.getNewTopics().add(entry.getValue());
					if (entry.getKey().after(newLastUpdateTime)) {
						newLastUpdateTime = entry.getKey();
					}
				}

			}

		}

		if (!this.newThemes.isEmpty()) {

			Iterator<Entry<Date, Theme>> iterator = this.newThemes.entrySet().iterator();
			while (iterator.hasNext()) {
				Entry<Date, Theme> entry = iterator.next();
				if (entry.getKey().after(lastUpdateTime))

				{

					data.getNewThemes().add(entry.getValue());
					if (entry.getKey().after(newLastUpdateTime)) {
						newLastUpdateTime = entry.getKey();
					}
				}

			}

		}

		if (!this.deletedItems.isEmpty()) {

			Iterator<Entry<Date, Item>> iterator = this.deletedItems.entrySet().iterator();
			while (iterator.hasNext()) {
				Entry<Date, Item> entry = iterator.next();
				if (entry.getKey().after(lastUpdateTime)) {

					data.getDeletedItems().add(entry.getValue());
					if (entry.getKey().after(newLastUpdateTime)) {
						newLastUpdateTime = entry.getKey();
					}
				}
			}
		}

		if (!this.deletedFrames.isEmpty()) {
			Iterator<Entry<Date, Frame>> iterator = this.deletedFrames.entrySet().iterator();
			while (iterator.hasNext()) {
				Entry<Date, Frame> entry = iterator.next();
				if (entry.getKey().after(lastUpdateTime)) {

					data.getDeletedFrames().add(entry.getValue());
					if (entry.getKey().after(newLastUpdateTime)) {
						newLastUpdateTime = entry.getKey();
					}
				}
			}
		}

		if (!this.deletedTopics.isEmpty()) {

			Iterator<Entry<Date, Topic>> iterator = this.deletedTopics.entrySet().iterator();
			while (iterator.hasNext()) {
				Entry<Date, Topic> entry = iterator.next();
				if (entry.getKey().after(lastUpdateTime))

				{

					data.getDeletedTopics().add(entry.getValue());
					if (entry.getKey().after(newLastUpdateTime)) {
						newLastUpdateTime = entry.getKey();
					}
				}
			}
		}

		if (!this.deletedThemes.isEmpty()) {
			Iterator<Entry<Date, Theme>> iterator = this.deletedThemes.entrySet().iterator();
			while (iterator.hasNext()) {
				Entry<Date, Theme> entry = iterator.next();
				if (entry.getKey().after(lastUpdateTime))

				{

					data.getDeletedThemes().add(entry.getValue());
					if (entry.getKey().after(newLastUpdateTime)) {
						newLastUpdateTime = entry.getKey();
					}
				}
			}
		}

		if (!this.updatedItems.isEmpty()) {
			Iterator<Entry<Date, Item>> iterator = this.updatedItems.entrySet().iterator();
			while (iterator.hasNext()) {
				Entry<Date, Item> entry = iterator.next();
				if (entry.getKey().after(lastUpdateTime))

				{
					data.getUpdatedItems().add(entry.getValue());
					if (entry.getKey().after(newLastUpdateTime)) {
						newLastUpdateTime = entry.getKey();
					}
				}
			}

		}
		if (!this.updatedFrames.isEmpty()) {
			Iterator<Entry<Date, Frame>> iterator = this.updatedFrames.entrySet().iterator();
			while (iterator.hasNext()) {
				Entry<Date, Frame> entry = iterator.next();
				if (entry.getKey().after(lastUpdateTime))

				{

					data.getUpdatedFrames().add(entry.getValue());
					if (entry.getKey().after(newLastUpdateTime)) {
						newLastUpdateTime = entry.getKey();
					}
				}
			}
		}

		if (!this.updatedTopics.isEmpty()) {

			Iterator<Entry<Date, Topic>> iterator = this.updatedTopics.entrySet().iterator();
			while (iterator.hasNext()) {
				Entry<Date, Topic> entry = iterator.next();
				if (entry.getKey().after(lastUpdateTime))

				{

					data.getUpdatedTopics().add(entry.getValue());
					if (entry.getKey().after(newLastUpdateTime)) {
						newLastUpdateTime = entry.getKey();
					}
				}
			}
		}

		if (!this.updatedThemes.isEmpty()) {
			Iterator<Entry<Date, Theme>> iterator = this.updatedThemes.entrySet().iterator();
			while (iterator.hasNext()) {
				Entry<Date, Theme> entry = iterator.next();
				if (entry.getKey().after(lastUpdateTime)) {
					data.getUpdatedThemes().add(entry.getValue());
					if (entry.getKey().after(newLastUpdateTime)) {
						newLastUpdateTime = entry.getKey();
					}
				}
			}
		}
		if (!this.newUsers.isEmpty()) {
			Iterator<Entry<Date, User>> iterator = this.newUsers.entrySet().iterator();
			while (iterator.hasNext()) {

				Entry<Date, User> entry = iterator.next();
				if (entry.getKey().after(lastUpdateTime)) {
					data.getNewUsers().add(entry.getValue());
					if (entry.getKey().after(newLastUpdateTime)) {
						newLastUpdateTime = entry.getKey();
					}

				}

			}
		}
		if (!this.updatedUsers.isEmpty()) {
			Iterator<Entry<Date, User>> iterator = this.updatedUsers.entrySet().iterator();
			while (iterator.hasNext()) {

				Entry<Date, User> entry = iterator.next();
				if (entry.getKey().after(lastUpdateTime)) {
					data.getUpdatedUsers().add(entry.getValue());
					if (entry.getKey().after(newLastUpdateTime)) {
						newLastUpdateTime = entry.getKey();
					}

				}

			}
		}
		if (!this.deletedUsers.isEmpty()) {
			Iterator<Entry<Date, String>> iterator = this.deletedUsers.entrySet().iterator();
			while (iterator.hasNext()) {

				Entry<Date, String> entry = iterator.next();
				if (entry.getKey().after(lastUpdateTime)) {
					data.getDeletedUsers().add(entry.getValue());
					if (entry.getKey().after(newLastUpdateTime)) {
						newLastUpdateTime = entry.getKey();
					}

				}

			}
		}

		if (this.activeComponents != null && !this.activeComponents.isEmpty()) {
			data.getActiveComponents().putAll(this.activeComponents);

		}

		this.registeredUsers.put(user, newLastUpdateTime);

		return data;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * eu.dnetlib.server.NotificationRegistry#registerUser(java.lang.String)
	 */
	public void registerUser(String user) {
		if (user != null) {
			Date date = new Date();
			log.info("\n\n" + "Register users::" + registeredUsers.size());
			for (Entry<String, Date> e : registeredUsers.entrySet()) {
				log.info("User id:" + e.getKey() + "  timestamp::" + e.getValue());
			}
			log.info("\n\n\nIN  registry!!!!!!!!\n\n add userId::" + user + "\n\n\n\n");

			this.registeredUsers.put(user, new Timestamp(date.getTime()));
			log.info("\n\n" + "Register users::" + registeredUsers.size());
			for (Entry<String, Date> e : registeredUsers.entrySet()) {
				log.info("User id:" + e.getKey() + "  timestamp::" + e.getValue());
			}
			log.info("\n\n");

		}
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see eu.dnetlib.server.NotificationRegistry#removeUser(java.lang.String)
	 */
	public void removeUser(String userId, ArrayList<String> userLockedComponents) {
		if (userId != null) {
			log.info("\n\n" + "Register users::" + registeredUsers.size());
			for (Entry<String, Date> e : registeredUsers.entrySet()) {
				log.info("User id:" + e.getKey() + "  timestamp::" + e.getValue());
			}
			log.info("\n\n\nIN  registry!!!!!!!!\n\n REMOVE userId::" + userId + "\n\n\n\n");

			this.registeredUsers.remove(userId);

			log.info("\n\n" + "Register users::" + registeredUsers.size());
			for (Entry<String, Date> e : registeredUsers.entrySet()) {
				log.info("User id:" + e.getKey() + "  timestamp::" + e.getValue());
			}
			log.info("\n\n");
			clearActive(userId, userLockedComponents);
		}
	}

	public void addUser(User user) {
		Date date = new Date();
		if (user != null) {
			Timestamp t = new Timestamp(date.getTime());
			log.info("\n\n+++++++++++++++++ added  new user at " + t);
			this.newUsers.put(t, user);
		} else {
			Timestamp t = new Timestamp(date.getTime());
			log.info("\n\n+++++++++++++++++ added  new user NUUUULLL at " + t);
		}
	}

	public void addDeletedUser(String id) {
		Date date = new Date();
		if (id != null) {
			Timestamp t = new Timestamp(date.getTime());
			log.info("\n\n+++++++++++++++++ delete user at " + t);
			this.deletedUsers.put(t, id);
			// TODO remove from active
			unmarkComponent(id);
		} else {
			Timestamp t = new Timestamp(date.getTime());
			log.info("\n\n+++++++++++++++++ delete user NUUUULLL at " + t);
		}
	}

	public void addUpdatedUser(User user) {
		Date date = new Date();
		if (user != null) {
			Timestamp t = new Timestamp(date.getTime());
			log.info("\n\n+++++++++++++++++ updated user at " + t);
			this.updatedUsers.put(t, user);
		} else {
			Timestamp t = new Timestamp(date.getTime());
			log.info("\n\n+++++++++++++++++ updated user NUUUULLL at " + t);
		}
	}

	public void clearActive() {

		log.info("clearing active....");

		this.activeComponents.clear();

		this.activeComponentsLog.clear();

	}

	public void clearActive(String userId, ArrayList<String> userLockedComponents) {
		if (userId != null) {

			Iterator<Entry<String, String>> iterator = this.activeComponents.entrySet().iterator();
			while (iterator.hasNext()) {
				Entry<String, String> e = iterator.next();
				if (e.getValue().equals(userId) && userLockedComponents.contains(e.getValue())) {

					this.activeComponents.remove(e.getKey());

					this.activeComponentsLog.remove(e.getKey());

				}
			}
		}
	}

	public static void setLog(Logger log) {
		ComponentsRegistry.log = log;
	}

	public ConcurrentHashMap<Date, Item> getNewItems() {
		return newItems;
	}

	public void setNewItems(ConcurrentHashMap<Date, Item> newItems) {
		this.newItems = newItems;
	}

	public ConcurrentHashMap<Date, Item> getUpdatedItems() {
		return updatedItems;
	}

	public void setUpdatedItems(ConcurrentHashMap<Date, Item> updatedItems) {
		this.updatedItems = updatedItems;
	}

	public ConcurrentHashMap<Date, Item> getDeletedItems() {
		return deletedItems;
	}

	public void setDeletedItems(ConcurrentHashMap<Date, Item> deletedItems) {
		this.deletedItems = deletedItems;
	}

	public ConcurrentHashMap<Date, Frame> getNewFrames() {
		return newFrames;
	}

	public void setNewFrames(ConcurrentHashMap<Date, Frame> newFrames) {
		this.newFrames = newFrames;
	}

	public ConcurrentHashMap<Date, Frame> getDeletedFrames() {
		return deletedFrames;
	}

	public void setDeletedFrames(ConcurrentHashMap<Date, Frame> deletedFrames) {
		this.deletedFrames = deletedFrames;
	}

	public ConcurrentHashMap<String, Date> getRegisteredUsers() {
		return registeredUsers;
	}

	public void setRegisteredUsers(ConcurrentHashMap<String, Date> registeredUsers) {
		this.registeredUsers = registeredUsers;
	}

	public Date getUpdateNumber() {
		return updateNumber;
	}

	public void setUpdateNumber(Date updateNumber) {
		this.updateNumber = updateNumber;
	}

	public ConcurrentHashMap<Date, Frame> getUpdatedFrames() {
		return updatedFrames;
	}

	public void setUpdatedFrames(ConcurrentHashMap<Date, Frame> updatedFrames) {
		this.updatedFrames = updatedFrames;
	}

	public ConcurrentHashMap<Date, Topic> getNewTopics() {
		return newTopics;
	}

	public void setNewTopics(ConcurrentHashMap<Date, Topic> newTopics) {
		this.newTopics = newTopics;
	}

	public ConcurrentHashMap<Date, Theme> getNewThemes() {
		return newThemes;
	}

	public void setNewThemes(ConcurrentHashMap<Date, Theme> newThemes) {
		this.newThemes = newThemes;
	}

	public ConcurrentHashMap<Date, Topic> getDeletedTopics() {
		return deletedTopics;
	}

	public void setDeletedTopics(ConcurrentHashMap<Date, Topic> deletedTopics) {
		this.deletedTopics = deletedTopics;
	}

	public ConcurrentHashMap<Date, Topic> getUpdatedTopics() {
		return updatedTopics;
	}

	public void setUpdatedTopics(ConcurrentHashMap<Date, Topic> updatedTopics) {
		this.updatedTopics = updatedTopics;
	}

	public ConcurrentHashMap<Date, Theme> getDeletedThemes() {
		return deletedThemes;
	}

	public void setDeletedThemes(ConcurrentHashMap<Date, Theme> deletedThemes) {
		this.deletedThemes = deletedThemes;
	}

	public ConcurrentHashMap<Date, Theme> getUpdatedThemes() {
		return updatedThemes;
	}

	public void setUpdatedThemes(ConcurrentHashMap<Date, Theme> updatedThemes) {
		this.updatedThemes = updatedThemes;
	}

	public ConcurrentHashMap<String, Date> getActiveComponentsLog() {
		return activeComponentsLog;
	}

	public void setActiveComponentsLog(ConcurrentHashMap<String, Date> activeComponentsLog) {
		this.activeComponentsLog = activeComponentsLog;
	}

	public ConcurrentHashMap<String, String> getActiveComponents() {
		return activeComponents;
	}

	public void setActiveComponents(ConcurrentHashMap<String, String> activeComponents) {
		this.activeComponents = activeComponents;
	}

	public ConcurrentHashMap<Date, User> getNewUsers() {
		return newUsers;
	}

	public void setNewUsers(ConcurrentHashMap<Date, User> newUsers) {
		this.newUsers = newUsers;
	}

	public ConcurrentHashMap<Date, User> getUpdatedUsers() {
		return updatedUsers;
	}

	public void setUpdatedUsers(ConcurrentHashMap<Date, User> updatedUsers) {
		this.updatedUsers = updatedUsers;
	}

	public ConcurrentHashMap<Date, String> getDeletedUsers() {
		return deletedUsers;
	}

	public void setDeletedUsers(ConcurrentHashMap<Date, String> deletedUsers) {
		this.deletedUsers = deletedUsers;
	}

	public void updateConfiguration(Configuration conf) {
		Date date = new Date();
		if (conf != null) {
			this.configurationDate = date;
			this.configuration = conf;
		}
	}

	public Configuration getConfiguration() {
		return configuration;
	}

}
