package uc.user;
import helpers.IPrefSerializer;
import helpers.PrefConverter;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CopyOnWriteArrayList;
import uc.IUser;
import uc.IUserChangedListener;
import uc.PI;
import uc.IStoppable.IStartable;
import uc.crypto.HashValue;
public class StoredPM implements IUserChangedListener ,IStartable {
/**
* delete messages after that amount of time..
* keep for 2 months..
*/
private static final long DELETION_TIME = 1000L * 3600L * 24L * 60L;
private static final byte MAX_MESSAGES = 5;
private final Map<HashValue,List<Message>> userToMessages =
Collections.synchronizedMap(new HashMap<HashValue, List<Message>>());
private final Population pop;
public StoredPM(Population pop) {
this.pop = pop;
}
public void stop() {
pop.unregisterUserChangedListener(this);
}
public void start() {
load();
pop.registerUserChangedListener(this);
}
private static class Message {
private final HashValue userID;
private final String message;
private final boolean me;
private final long date;
public Message(HashValue userID, String message, boolean me, long date) {
super();
this.userID = userID;
this.message = message;
this.me = me;
this.date = date;
}
public void send(IUser usr) {
SimpleDateFormat sdf = new SimpleDateFormat("[dd.MM. HH:mm]");
usr.sendPM(sdf.format(new Date(date))+" "+message, me,false);
}
public boolean shouldBeDeleted() {
return System.currentTimeMillis()- date > DELETION_TIME;
}
}
public static class MessageTranslater implements IPrefSerializer<Message> {
public String[] serialize(Message t) {
return new String[]{
t.userID.toString(),
t.message,
""+t.me,
""+t.date
};
}
public Message unSerialize(String[] all) {
return new Message(HashValue.createHash(all[0]),
all[1],
Boolean.parseBoolean(all[2]),
Long.parseLong(all[3]) );
}
}
private void load() {
List<Message> messages = PrefConverter.parseString(PI.get(PI.storedPMs), new MessageTranslater());
for (Message mes:messages) {
addPM(mes);
}
}
private void store() {
List<Message> mesList = new ArrayList<Message>();
for (List<Message> list:userToMessages.values()) {
mesList.addAll(list);
}
String s = PrefConverter.createList(mesList, new MessageTranslater());
PI.put(PI.storedPMs, s);
}
/**
* stores a private message to be sent when the user comes online again..
*
* @param target
* @param message
* @param me
* @return true if successful... number of PMs per user is limited..
* otherwise sending of PMs on connect will trigger spam controls..
*/
public boolean storePM(IUser target,String message,boolean me) {
Message mes = new Message(target.getUserid(),message,me,System.currentTimeMillis());
boolean ret = addPM(mes);
store();
return ret;
}
private boolean addPM(Message mes) {
if (!mes.shouldBeDeleted()) {
List<Message> messageList = userToMessages.get(mes.userID);
if (messageList == null) {
messageList = new CopyOnWriteArrayList<Message>();
userToMessages.put(mes.userID, messageList);
}
if (messageList.size() < MAX_MESSAGES) {
messageList.add(mes);
return true;
}
}
return false;
}
public void changed(UserChangeEvent uce) {
if (uce.getType() == UserChange.CONNECTED &&
userToMessages.containsKey(uce.getChanged().getUserid())) {
List<Message> messageList = userToMessages.remove(uce.getChanged().getUserid());
if (messageList != null) {
for (Message mes:messageList) {
mes.send(uce.getChanged());
}
store();
}
}
}
}