package ru.yandex.wmconsole.data;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import ru.yandex.wmconsole.data.info.NotificationInfo;

/**
 * @author Andrey Mima (amima@yandex-team.ru)
 */
public class NotificationsForUser {
    private static final Logger log = LoggerFactory.getLogger(NotificationsForUser.class);

    private final Map<Integer, List<NotificationInfo>> notificationsByType = new HashMap<Integer, List<NotificationInfo>>();
    private final List<NotificationInfo> allNotifications = new ArrayList<NotificationInfo>();
    private final Long userId;

    public NotificationsForUser(Long userId) {
        this.userId = userId;
    }

    public Long getUserId() {
        return userId;
    }

    public void addNotification(NotificationInfo notification) {
        if (!notification.getUserId().equals(userId)) {
            log.error("IllegalArgumentException in " + getClass().getName() +
                    ": user in notification is not equal to expected");
            throw new IllegalArgumentException("User in notification is not equal to expected");
        }

        Integer type = notification.getNotificationType();
        if (!notificationsByType.containsKey(type)) {
            notificationsByType.put(type, new ArrayList<NotificationInfo>());
        }

        if (!notificationsByType.get(type).contains(notification)) {
            notificationsByType.get(type).add(notification);
            allNotifications.add(notification);
        }
    }

    public Set<Integer> getTypes() {
        return notificationsByType.keySet();
    }

    public boolean containsType(Integer type) {
        return notificationsByType.containsKey(type);
    }

    /**
     * <b>MUST BE MODIFIABLE</b> (it.remove is used)
     * @return all notifications
     */
    public List<NotificationInfo> getAllNotifications() {
        return allNotifications;
    } //TODO REFACTOR

    /**
     * <b>MUST BE MODIFIABLE</b> (it.remove is used)
     * @param type notification type
     * @return type notifications
     */
    public List<NotificationInfo> getNotifications(Integer type) {
        if (!notificationsByType.containsKey(type)) {
            Collections.emptyList();
        }

        return notificationsByType.get(type);
    } //TODO REFACTOR

    public void addAll(List<NotificationInfo> notifications) {
        for (NotificationInfo notification : notifications) {
            addNotification(notification);
        }
    }

    public boolean isEmpty() {
        return allNotifications.isEmpty();
    }

    //todo refactor
    public static NotificationsForUser getCopy(NotificationsForUser other) {
        NotificationsForUser copy = new NotificationsForUser(other.getUserId());
        copy.addAll(other.getAllNotifications());
        return copy;
    }
}
