package floobits.common;
import floobits.common.interfaces.IContext;
import floobits.common.protocol.FlooUser;
import floobits.common.protocol.buf.Buf;
import floobits.common.protocol.json.receive.FlooHighlight;
import floobits.common.protocol.json.send.RoomInfoResponse;
import floobits.utilities.Flog;
import org.apache.commons.io.FilenameUtils;
import org.jetbrains.annotations.Nullable;
import java.util.*;
import java.util.concurrent.ScheduledFuture;
public class FloobitsState {
public FlooHighlight lastHighlight;
public HashMap<String, FlooHighlight> lastUserHighlights = new HashMap<String, FlooHighlight>();
private Boolean following = false;
private ScheduledFuture pausedFollowing;
public HashSet<String> perms = new HashSet<String>();
public Map<Integer, FlooUser> users = new HashMap<Integer, FlooUser>();
@Nullable HashMap<Integer, Buf> bufs = new HashMap<Integer, Buf>();
final HashMap<String, Integer> pathsToIds = new HashMap<String, Integer>();
private int connectionId;
public boolean readOnly = false;
public String username = "";
private IContext context;
public FlooUrl url;
public List<String> followedUsers = new ArrayList<String>();
public FloobitsState(IContext context, FlooUrl flooUrl) {
this.context = context;
url = flooUrl;
}
public boolean can(String perm) {
if (!context.isJoined())
return false;
if (!perms.contains(perm)) {
Flog.info("we can't do that because perms");
return false;
}
return true;
}
public void handleRoomInfo(RoomInfoResponse ri) {
Flog.info("Got roominfo with userId %d", connectionId);
users = ri.users;
perms = new HashSet<String>(Arrays.asList(ri.perms));
if (!can("patch")) {
readOnly = true;
context.statusMessage("You don't have permission to edit files in this workspace. All documents will be set to read-only.");
}
connectionId = Integer.parseInt(ri.user_id);
for (FlooUser user : ri.users.values()) {
context.addUser(user);
}
}
public void setBufPath(Buf buf, String newPath) {
pathsToIds.remove(buf.path);
buf.path = FilenameUtils.separatorsToUnix(newPath);
pathsToIds.put(buf.path, buf.id);
}
public @Nullable
Buf getBufByPath(String absPath) {
String relPath = context.toProjectRelPath(absPath);
if (relPath == null) {
return null;
}
Integer id = pathsToIds.get(FilenameUtils.separatorsToUnix(relPath));
if (id == null || bufs == null) {
return null;
}
return bufs.get(id);
}
public String getUsername(int userId) {
FlooUser user = users.get(userId);
if (user == null) {
return "";
}
return user.username;
}
public String getGravatar(int userId) {
FlooUser user = users.get(userId);
if (user == null) {
return "";
}
return user.gravatar;
}
/**
* Get a user by their connection id (userId).
* @param userId
* @return null or the FlooUser object for the connection id.
*/
public FlooUser getUser(int userId) {
return users.get(userId);
}
public void addUser(FlooUser user) {
users.put(user.user_id, user);
context.addUser(user);
}
public void removeUser(int userId) {
FlooUser u = users.get(userId);
if (u == null) {
return;
}
context.removeUser(u);
}
public int getMyConnectionId() {
return connectionId;
}
public void changePermsForUser(int userId, String[] permissions) {
FlooUser user = getUser(userId);
if (user == null) {
return;
}
List<String> givenPerms = java.util.Arrays.asList(permissions);
Set<String> translatedPermsSet = new HashSet<String>();
HashMap<String, String[]> permTypes = new HashMap<String, String[]>();
permTypes.put("edit_room", new String[]{
"patch", "get_buf", "set_buf", "create_buf", "delete_buf", "rename_buf", "set_temp_data", "delete_temp_data",
"highlight", "msg", "datamsg", "create_term", "term_stdin", "delete_term", "update_term", "term_stdout", "saved"
});
permTypes.put("view_room", new String[]{"get_buf", "ping", "pong"});
permTypes.put("request_perms", new String[]{"get_buf", "request_perms"});
permTypes.put("admin_room", new String[]{"kick", "pull_repo", "perms"});
for (Map.Entry<String, String[]> entry : permTypes.entrySet()) {
if (givenPerms.contains(entry.getKey())) {
Collections.addAll(translatedPermsSet, entry.getValue());
}
}
user.perms = translatedPermsSet.toArray(new String[translatedPermsSet.size()]);
}
public void shutdown() {
bufs = null;
}
public Boolean getFollowing() {
return following;
}
public void setFollowing(Boolean following) {
this.pauseFollowing(false);
this.following = following;
if (!following) {
this.followedUsers.clear();
if (context.getFlooHandler() == null) {
return;
}
context.updateFollowing();
}
}
public Boolean getPausedFollowing() {
return pausedFollowing != null;
}
public void pauseFollowing(Boolean pauseFollowing) {
/*
Possible states:
Not following, not paused.
Following, not paused.
Following, paused.
Impossible state:
Not following, paused. Paused means following, just not active. Anytime we set follow, we must cancel any pause.
*/
if (this.pausedFollowing != null) {
following = true;
this.pausedFollowing.cancel(true);
}
this.pausedFollowing = null;
if (pauseFollowing) {
if (!following) {
return;
}
following = false;
this.pausedFollowing = context.setTimeout(2000, new Runnable() {
@Override
public void run() {
pauseFollowing(false);
}
});
}
}
public void setFollowedUsers(List<String> followedUsers) {
this.followedUsers = followedUsers;
setFollowing(followedUsers.size() > 0);
context.updateFollowing();
}
public int numBufs() {
return pathsToIds.size();
}
}