package jetbrains.buildServer.serverSide;

import com.intellij.openapi.diagnostic.Logger;
import jetbrains.buildServer.users.User;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
* @author Eugene Petrenko
*         Created: 31.03.2010 21:03:55
*/
public class Room {
  private final static Logger LOG = Logger.getInstance(Room.class.getName());

  private final int myRoomId;
  private final Map<Long, UserInfo> myMembers = new ConcurrentHashMap<Long, UserInfo>();

  public Room(int roomId) {
    myRoomId = roomId;
  }

  public int getRoomId() {
    return myRoomId;
  }

  public boolean canInsertUser() {
    return getMembersCount() < 2;
  }

  public int getMembersCount() {
    killIdleMembers();
    return myMembers.size();
  }

  public boolean containsUser(@Nullable User user) {
    return user == null || myMembers.containsKey(user.getId());
  }

  public void addUser(@NotNull User user) {
    LOG.warn("User " + user.getUsername() + " was added to room: " + myRoomId);
    myMembers.put(user.getId(), new UserInfo(user));
  }

  public void mergeWith(Room another) {
    LOG.warn("Room " + another.getRoomId() + " was merged to room: " + myRoomId);
    myMembers.putAll(another.myMembers);
    another.myMembers.clear();
  }

  public Date getLastMessageDate() {
    Date date = null;
    for (UserInfo info : myMembers.values()) {
      final Date la = info.getLastAccess();
      if (date == null || date.compareTo(la) < 0) {
        date = la;
      }
    }
    return date != null ? date : new Date(0);
  }

  public void killIdleMembers() {
    List<Long> toKill = new ArrayList<Long>();
    for (Map.Entry<Long, UserInfo> entry : myMembers.entrySet()) {
      if (entry.getValue().isIdle(new Date())) {
        toKill.add(entry.getKey());
      }
    }

    for (Long aLong : toKill) {
      myMembers.remove(aLong);
    }

    if (!toKill.isEmpty())
      LOG.warn("Idle members " + toKill + " were removed from the room: " + myRoomId);
  }

  public void ping(User user) {
    if (user == null) return;
    final UserInfo info = myMembers.get(user.getId());
    if (info != null) {
      info.ping();
    }
  }
}