package ru.denull.wire.model;
import java.util.HashMap;
import java.util.HashSet;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
import ru.denull.mtproto.DataService;
import ru.denull.mtproto.Server;
import ru.denull.wire.Utils;
import tl.TInputPeer;
import tl.TLObject;
import tl.TUser;
import tl.messages.SetTyping;
public class TypingManager {
DataService service;
public TypingCallback callback = null;
public HashMap<Integer, Integer> typed = new HashMap<Integer, Integer>();
public HashMap<Integer, Boolean> users = new HashMap<Integer, Boolean>();
public HashMap<Integer, ScheduledFuture<?>> usersFuture = new HashMap<Integer, ScheduledFuture<?>>();
public HashMap<Integer, HashSet<Integer>> chats = new HashMap<Integer, HashSet<Integer>>();
public HashMap<Integer, HashMap<Integer, ScheduledFuture<?>>> chatsFuture = new HashMap<Integer, HashMap<Integer,ScheduledFuture<?>>>();
public interface TypingCallback {
public void update(int peer_id);
}
public TypingManager(DataService service) {
this.service = service;
}
// called on each keypress
public void startTyping(TInputPeer peer) {
if (peer == null) return;
int peer_id = Utils.getPeerID(peer, service.me);
if (typed.get(peer_id) != null && System.currentTimeMillis() / 1000 - typed.get(peer_id) < 4) {
return;
}
typed.put(peer_id, (int) (System.currentTimeMillis() / 1000));
service.mainServer.call(new SetTyping(peer, true), new Server.RPCCallback<TLObject>() {
public void done(TLObject result) {
}
public void error(int code, String message) {
}
});
}
// called when user definitely stopped typing (closed keyboard, moved from fragment)
public void stopTyping(TInputPeer peer) {
if (peer == null) return;
int peer_id = Utils.getPeerID(peer, service.me);
if (System.currentTimeMillis() / 1000 - typed.get(peer_id) > 5) {
return;
}
typed.remove(Utils.getPeerID(peer, service.me));
service.mainServer.call(new SetTyping(peer, false), new Server.RPCCallback<TLObject>() {
public void done(TLObject result) {
}
public void error(int code, String message) {
}
});
}
public void userEncryptedTyping(int chat_id) {
userTyping(-chat_id, true);
}
public void userTyping(int user_id) {
userTyping(user_id, true);
}
public void userTyping(final int user_id, boolean isTyping) {
if (isTyping) {
ScheduledFuture<?> future = usersFuture.get(user_id);
if (future != null) {
usersFuture.remove(user_id);
future.cancel(true);
}
usersFuture.put(user_id, service.scheduledPool.schedule(new Runnable() {
public void run() {
userTyping(user_id, false);
}
}, 5, TimeUnit.SECONDS));
}
users.put(user_id, isTyping);
if (callback != null) {
callback.update(user_id);
}
}
public void userTyping(int peer_id, int user_id) {
userTyping(peer_id, user_id, true);
}
public void userTyping(final int peer_id, final int user_id, boolean isTyping) {
if (isTyping) {
if (chatsFuture.get(peer_id) != null) {
ScheduledFuture<?> future = chatsFuture.get(peer_id).get(user_id);
if (future != null) {
usersFuture.remove(user_id);
future.cancel(true);
}
} else {
chatsFuture.put(peer_id, new HashMap<Integer, ScheduledFuture<?>>());
}
chatsFuture.get(peer_id).put(user_id, service.scheduledPool.schedule(new Runnable() {
public void run() {
userTyping(peer_id, user_id, false);
}
}, 5, TimeUnit.SECONDS));
}
if (chats.get(peer_id) == null) {
chats.put(peer_id, new HashSet<Integer>());
}
if (isTyping) {
chats.get(peer_id).add(user_id);
} else {
chats.get(peer_id).remove(user_id);
}
if (callback != null) {
callback.update(peer_id);
}
}
// checks if user is typing now
public boolean isTyping(int user_id) {
return users.containsKey(user_id) && users.get(user_id);
}
// return null if nobody in chat is typing, formatted string otherwise
public String areTyping(int chat_id) {
HashSet<Integer> typing = chats.get(-chat_id);
if (typing == null || typing.size() == 0) {
return null;
}
if (typing.size() > 2) {
return typing.size() + " участника печатают...";
}
int num = 0;
String result = "";
for (int user_id : typing) {
TUser user = service.userManager.get(user_id);
if (num > 0) {
result += ", ";
}
result += user.first_name;
num++;
}
return result + (typing.size() == 1 ? " печатает" : " печатают") + "...";
}
// null if not typing, formatted string otherwise
public String getStatus(int peer_id, boolean full) {
if (peer_id > 0) {
if (!isTyping(peer_id)) {
return null;
}
if (!full) {
return "печатает...";
}
TUser user = service.userManager.get(peer_id);
return user.first_name + " " + user.last_name + " печатает...";
} else {
return areTyping(-peer_id);
}
}
}