package org.limewire.ui.swing.friends.chat;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import javax.swing.Timer;
import org.jdesktop.beans.AbstractBean;
import org.limewire.friend.api.Friend;
import org.limewire.friend.api.FriendPresence;
import org.limewire.friend.api.MessageReader;
import org.limewire.friend.api.MessageWriter;
import org.limewire.friend.api.feature.LimewireFeature;
import org.limewire.ui.swing.util.SwingUtils;
class ChatFriendImpl extends AbstractBean implements ChatFriend {
private boolean chatting;
private final Friend friend;
private String status;
private FriendPresence.Mode mode;
private long chatStartTime;
private boolean hasUnviewedMessages;
private Timer timer;
private int flashCount = 0;
ChatFriendImpl(final FriendPresence presence) {
this.friend = presence.getFriend();
this.status = presence.getStatus();
this.mode = presence.getMode();
}
@Override
public Friend getFriend() {
return friend;
}
@Override
public String getID() {
return friend.getId();
}
@Override
public FriendPresence.Mode getMode() {
return mode;
}
void setMode(FriendPresence.Mode mode) {
FriendPresence.Mode oldMode = getMode();
this.mode = mode;
firePropertyChange("mode", oldMode, mode);
}
@Override
public String getName() {
return friend.getRenderName();
}
@Override
public String getStatus() {
return status;
}
void setStatus(String status) {
String oldStatus = getStatus();
this.status = status;
firePropertyChange("status", oldStatus, status);
}
@Override
public boolean isChatting() {
return chatting;
}
void setChatting(final boolean chatting) {
final boolean oldChatting = isChatting();
this.chatting = chatting;
SwingUtils.invokeLater(new Runnable(){
public void run() {
firePropertyChange("chatting", oldChatting, chatting);
}
});
}
@Override
public MessageWriter createChat(MessageReader reader) {
return friend.createChat(reader);
}
@Override
public void startChat() {
if (isChatting() == false) {
chatStartTime = System.currentTimeMillis();
setChatting(true);
}
}
@Override
public void update() {
// If there's an available presence, set to "Available"
// If no available presence, use highest priority presence.
FriendPresence presence = getPresenceForModeAndStatus();
if (presence != null) {
setStatus(presence.getStatus());
setMode(presence.getMode());
}
}
@Override
public void stopChat() {
stopTimer();
setChatting(false);
setHasUnviewedMessages(false);
}
@Override
public long getChatStartTime() {
return chatStartTime;
}
@Override
public boolean isSignedInToLimewire() {
for (FriendPresence presence : friend.getPresences().values()) {
if (presence.getFeature(LimewireFeature.ID) != null) {
return true;
}
}
return false;
}
@Override
public boolean isSignedIn() {
return friend.isSignedIn();
}
@Override
public boolean hasUnviewedMessages() {
return hasUnviewedMessages;
}
public boolean isFlashState() {
return flashCount % 2 == 0;
}
@Override
public void setHasUnviewedMessages(boolean hasMessages) {
if(hasMessages)
startTimer();
else
stopTimer();
boolean oldHasUnviewedMessages = hasUnviewedMessages;
hasUnviewedMessages = hasMessages;
firePropertyChange("receivingUnviewedMessages", oldHasUnviewedMessages, hasMessages);
}
/**
* Starts a timer to flash the chat icon when a new
* message has been received but the friend is not selected.
*/
private void startTimer() {
if(timer == null) {
timer = new Timer(1500, new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
if(flashCount > 4)
stopTimer();
firePropertyChange("flashIncrement", flashCount, flashCount + 1);
flashCount += 1;
}
});
timer.start();
} else {
flashCount = 0;
timer.restart();
}
}
private void stopTimer() {
if(timer != null) {
timer.stop();
flashCount = 0;
timer = null;
}
}
private FriendPresence getPresenceForModeAndStatus() {
ArrayList<FriendPresence> presences = new ArrayList<FriendPresence>(friend.getPresences().values());
Collections.sort(presences, new ModeAndPriorityPresenceComparator());
return presences.size() == 0 ? null : presences.get(presences.size()-1);
}
private static class ModeAndPriorityPresenceComparator implements Comparator<FriendPresence> {
@Override
public int compare(FriendPresence o1, FriendPresence o2) {
if (!o1.getMode().equals(o2.getMode())) {
if (o1.getMode() == FriendPresence.Mode.available) {
return 1;
} else if (o2.getMode() == FriendPresence.Mode.available) {
return -1;
}
}
return Integer.valueOf(o1.getPriority()).compareTo(o2.getPriority());
}
}
}