package net.thesocialos.client.chat;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import net.thesocialos.client.CacheLayer;
import net.thesocialos.client.TheSocialOS;
import net.thesocialos.client.app.AppConstants;
import net.thesocialos.client.chat.events.ChatCloseConversation;
import net.thesocialos.client.chat.events.ChatEvent;
import net.thesocialos.client.chat.events.ChatEventHandler;
import net.thesocialos.client.chat.events.ChatHideConversation;
import net.thesocialos.client.chat.events.ChatMenuMinimize;
import net.thesocialos.client.chat.events.ChatOpenConversation;
import net.thesocialos.client.chat.events.ChatRecieveMessage;
import net.thesocialos.client.chat.events.ChatSendMessage;
import net.thesocialos.client.chat.events.ChatStateChange;
import net.thesocialos.client.chat.events.ChatTopConversations;
import net.thesocialos.client.chat.view.ChatConversationView;
import net.thesocialos.client.chat.view.ChatMenuView;
import net.thesocialos.client.chat.view.ListChatBlocks;
import net.thesocialos.client.desktop.DesktopEventOnMinimize;
import net.thesocialos.client.desktop.DesktopEventOnOpen;
import net.thesocialos.client.desktop.window.Footer;
import net.thesocialos.client.desktop.window.MyCaption;
import net.thesocialos.client.event.ChannelClose;
import net.thesocialos.client.event.ChannelEvent;
import net.thesocialos.client.event.ChannelEventHandler;
import net.thesocialos.client.event.ChannelOpen;
import net.thesocialos.client.event.ContactsChangeEvent;
import net.thesocialos.client.event.ContactsChangeEventHandler;
import net.thesocialos.client.helper.RPCXSRF;
import net.thesocialos.client.service.ChatService;
import net.thesocialos.client.service.ChatServiceAsync;
import net.thesocialos.shared.ChannelApiEvents.ChApiChatUserChngState.STATETYPE;
import net.thesocialos.shared.model.Lines;
import net.thesocialos.shared.model.User;
import com.google.gwt.core.client.GWT;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.WindowPanelLayout;
import com.googlecode.objectify.Key;
public class ChatManager {
private HashMap<Key<User>, ChatConversationPresenter> conversations = new HashMap<Key<User>, ChatConversationPresenter>();
ChatMenuPresenter chatMenuPresenter;
ListChatBlockPresenter chatListChatBlocksPresenter;
ChatServiceAsync chatService = GWT.create(ChatService.class);
/** If the chat is hide **/
boolean isHide = false;
boolean disconnect = false;
public ChatManager() {
chatMenuPresenter = new ChatMenuPresenter(new ChatMenuView(), this);
chatListChatBlocksPresenter = new ListChatBlockPresenter(new ListChatBlocks());
bindHandlers();
TheSocialOS.getEventBus().fireEvent(new DesktopEventOnOpen(chatMenuPresenter));
TheSocialOS.getEventBus().fireEvent(new DesktopEventOnOpen(chatListChatBlocksPresenter));
getContacts();
init();
}
private void bindHandlers() {
TheSocialOS.getEventBus().addHandler(ChatEvent.TYPE, new ChatEventHandler() {
@Override
public void onSendMessage(ChatSendMessage event) {
sendText(event.getUserKey(), event.getMessage());
}
@Override
public void onRecieveMessage(final ChatRecieveMessage event) {
sendMessage(event.getUserKey(), event.getLine());
if (isHide) {
TheSocialOS.getEventBus().fireEvent(
new DesktopEventOnMinimize(conversations.get(event.getUserKey()), true));
chatMenuPresenter.addUnreadMessage();
}
chatListChatBlocksPresenter.messagePending(event.getUserKey());
}
@Override
public void onConversationOpen(final ChatOpenConversation event) {
OpenWindow(event.getUserKey(), new AsyncCallback<Boolean>() {
@Override
public void onFailure(Throwable caught) {
// TODO Auto-generated method stub
}
@Override
public void onSuccess(Boolean result) {
}
});
}
@Override
public void onConversationHide(ChatHideConversation event) {
hideRestoreWindow(event.getUserKey());
}
@Override
public void onConversationClose(ChatCloseConversation event) {
chatListChatBlocksPresenter.removeConversationBlock(event.getUserKey());
}
@Override
public void onChangeState(ChatStateChange event) {
// TODO Auto-generated method stub
chatMenuPresenter.changeContactState(event.getUserEmail(), event.getStateType(), event.getCustomState());
// changeState(event.getUserEmail(
}
@Override
public void onTopConversation(ChatTopConversations event) {
activateConversationsBlock(event.getUserKey());
}
@Override
public void onChatMenuHide(ChatMenuMinimize event) {
if (isHide) {
chatListChatBlocksPresenter.hide(false);
chatMenuPresenter.hideRestore();
} else {
chatListChatBlocksPresenter.hide(true);
chatMenuPresenter.hideRestore();
hideAllWindows();
}
}
});
TheSocialOS.getEventBus().addHandler(ContactsChangeEvent.TYPE, new ContactsChangeEventHandler() {
@Override
public void onContactsChange(ContactsChangeEvent event) {
getContacts();
}
});
TheSocialOS.getEventBus().addHandler(ChannelEvent.TYPE, new ChannelEventHandler() {
@Override
public void onChannelDisconnect(ChannelClose event) {
// TODO Auto-generated method stub
disconnect = true;
hideAllWindows();
chatListChatBlocksPresenter.hide(true);
chatMenuPresenter.disconnected(true);
}
@Override
public void onChannelConnect(ChannelOpen event) {
disconnect = false;
chatListChatBlocksPresenter.hide(false);
chatMenuPresenter.disconnected(false);
}
});
}
private void getContacts() {
CacheLayer.ContactCalls.getContactsWithoutKey(true, new AsyncCallback<Map<String, User>>() {
@Override
public void onSuccess(Map<String, User> result) {
chatMenuPresenter.refeshContacts(result);
}
@Override
public void onFailure(Throwable caught) {
// TODO Auto-generated method stub
}
});
}
private void init() {
changeState(STATETYPE.ONLINE, null);
}
/**
* Create a new Window of chat
*
* @param userEmail
* @return
*/
private ChatConversationPresenter createConversation(Key<User> userKey) {
return new ChatConversationPresenter(AppConstants.CHAT, "Chat to" + userKey.getName(), null, userKey,
new WindowPanelLayout(false, false, new MyCaption(), new Footer()), new ChatConversationView());
}
/**
* Send a message in one chat
*
* @param display
* @param message
*/
private void sendMessage(final Key<User> contact, final Lines line) {
OpenWindow(contact, new AsyncCallback<Boolean>() {
@Override
public void onFailure(Throwable caught) {
}
@Override
public void onSuccess(Boolean result) {
if (result) conversations.get(contact).writeMessage(line);
}
});
}
private void OpenWindow(final Key<User> contact, final AsyncCallback<Boolean> callback) {
if (CacheLayer.ContactCalls.isContact(contact)) {
if (conversations.containsKey(contact)) {
ChatConversationPresenter conversationPresenter = conversations.get(contact);
if (conversationPresenter.isMinimized()) callback.onSuccess(true);
else {
chatListChatBlocksPresenter.addConvesationBlock(contact);
TheSocialOS.getEventBus().fireEvent(new DesktopEventOnOpen(conversationPresenter));
callback.onSuccess(true);
}
} else {
ChatConversationPresenter chatConversation = createConversation(contact);
conversations.put(contact, chatConversation);
TheSocialOS.getEventBus().fireEvent(new DesktopEventOnOpen(chatConversation));
chatListChatBlocksPresenter.addConvesationBlock(contact);
callback.onSuccess(true);
}
} else
CacheLayer.ContactCalls.updateContacts(new AsyncCallback<Boolean>() {
@Override
public void onSuccess(Boolean result) {
if (result == false) callback.onSuccess(false);
if (CacheLayer.ContactCalls.isContact(contact))
if (conversations.containsKey(contact)) conversations.get(contact).setOnTop();
else {
ChatConversationPresenter chatConversation = createConversation(contact);
conversations.put(contact, chatConversation);
TheSocialOS.getEventBus().fireEvent(new DesktopEventOnOpen(chatConversation));
chatListChatBlocksPresenter.addConvesationBlock(contact);
callback.onSuccess(true);
}
}
@Override
public void onFailure(Throwable caught) {
// TODO Auto-generated method stub
}
});
}
private void hideRestoreWindow(Key<User> userKey) {
if (!conversations.containsKey(userKey)) return;
if (conversations.get(userKey).isMinimized()) activateConversationsBlock(userKey);
else {
activateConversationsBlock(userKey);
chatListChatBlocksPresenter.setActivateConversationBlock(userKey, true);
}
TheSocialOS.getEventBus().fireEvent(new DesktopEventOnMinimize(conversations.get(userKey), false));
}
private void hideAllWindows() {
Set<Entry<Key<User>, ChatConversationPresenter>> set = conversations.entrySet();
Iterator<Entry<Key<User>, ChatConversationPresenter>> iterator = set.iterator();
while (iterator.hasNext()) {
Entry<Key<User>, ChatConversationPresenter> entry = iterator.next();
// activateConversationsBlock(entry.getKey());
chatListChatBlocksPresenter.setActivateConversationBlock(entry.getKey(), true);
TheSocialOS.getEventBus().fireEvent(new DesktopEventOnMinimize(entry.getValue(), true));
}
}
private void activateConversationsBlock(Key<User> userKey) {
chatListChatBlocksPresenter.modifyConversationsBlock(userKey);
}
/**
* Change user state
*
* @param stateType
* @param customState
*/
protected void changeState(final STATETYPE stateType, String customState) {
CacheLayer.UserCalls.setChatState(stateType, customState, new AsyncCallback<Void>() {
@Override
public void onSuccess(Void result) {
chatMenuPresenter.changeUserState(stateType);
}
@Override
public void onFailure(Throwable caught) {
// TODO Auto-generated method stub
}
});
/*
* ChatDisplay display = getConversation(email); if (display != null) display.setState(stateType, customState);
*/
}
private void sendText(final Key<User> keyContact, final String message) {
new RPCXSRF<Long>(chatService) {
@Override
protected void XSRFcallService(AsyncCallback<Long> cb) {
// TODO Auto-generated method stub
chatService.sendText(keyContact, message, cb);
}
@Override
public void onSuccess(Long time) {
conversations.get(keyContact).writeMessage(new Lines(message, null, time));
}
@Override
public void onFailure(Throwable caught) {
System.out.println(caught);
}
}.retry(3);
}
}