/***************************************************************************
* Copyright 2006-2016 by Christian Ihle *
* contact@kouchat.net *
* *
* This file is part of KouChat. *
* *
* KouChat is free software; you can redistribute it and/or modify *
* it under the terms of the GNU Lesser General Public License as *
* published by the Free Software Foundation, either version 3 of *
* the License, or (at your option) any later version. *
* *
* KouChat is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
* Lesser General Public License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public *
* License along with KouChat. *
* If not, see <http://www.gnu.org/licenses/>. *
***************************************************************************/
package net.usikkert.kouchat.android.notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.graphics.Typeface;
import android.support.v7.app.NotificationCompat;
import android.text.SpannableString;
import android.text.style.StyleSpan;
import net.usikkert.kouchat.android.R;
import net.usikkert.kouchat.android.controller.MainChatController;
import net.usikkert.kouchat.android.controller.PrivateChatController;
import net.usikkert.kouchat.android.settings.AndroidSettings;
import net.usikkert.kouchat.misc.User;
import org.apache.commons.collections4.queue.CircularFifoQueue;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
/**
* Service for handling new message notifications.
*
* @author Christian Ihle
*/
public class MessageNotificationService {
private static final int MESSAGE_NOTIFICATION_ID = 100000000;
private static final int MAX_MESSAGES = 5; // Stores the 5 newest messages
private final Context context;
private final NotificationManager notificationManager;
private final NotificationHelper notificationHelper;
private final Collection<CharSequence> messages;
private final Map<User, Collection<String>> privateMessages;
private final Map<User, Integer> privateMessageCount;
private int messageCount;
public MessageNotificationService(final Context context,
final NotificationManager notificationManager,
final AndroidSettings settings) {
this.context = context;
this.notificationManager = notificationManager;
notificationHelper = new NotificationHelper(context, settings);
messages = new CircularFifoQueue<>(MAX_MESSAGES);
privateMessages = new HashMap<>();
privateMessageCount = new HashMap<>();
}
public void notifyNewMainChatMessage(final User user, final String message) {
final CharSequence latestMessage = createMainChatMessage(user, message);
addMainChatMessageToList(latestMessage);
final NotificationCompat.Builder notification = new NotificationCompat.Builder(context);
notification.setTicker(context.getString(R.string.notification_new_message_ticker, user.getNick()));
notification.setContentTitle(context.getString(R.string.notification_main_chat));
notification.setContentText(latestMessage);
notification.setNumber(messageCount);
notification.setSmallIcon(R.drawable.ic_stat_notify_activity);
notification.setStyle(fillMainChatInbox());
notification.setContentIntent(createIntentForMainChat());
notification.setPriority(NotificationCompat.PRIORITY_MAX);
notification.setCategory(NotificationCompat.CATEGORY_MESSAGE);
notificationHelper.setFeedbackEffects(notification);
notificationManager.notify(MESSAGE_NOTIFICATION_ID, notification.build());
}
public void notifyNewPrivateChatMessage(final User user, final String message) {
addPrivateMessageToList(user, message);
final NotificationCompat.Builder notification = new NotificationCompat.Builder(context);
notification.setTicker(context.getString(R.string.notification_new_private_message_ticker, user.getNick()));
notification.setContentTitle(user.getNick());
notification.setContentText(message);
notification.setNumber(privateMessageCount.get(user));
notification.setSmallIcon(R.drawable.ic_stat_notify_activity);
notification.setStyle(fillPrivateChatInbox(user));
notification.setContentIntent(createIntentForPrivateChat(user));
notification.setPriority(NotificationCompat.PRIORITY_MAX);
notification.setCategory(NotificationCompat.CATEGORY_MESSAGE);
notificationHelper.setFeedbackEffects(notification);
notificationManager.notify(getNotificationIdForUser(user), notification.build());
}
private CharSequence createMainChatMessage(final User user, final String message) {
final String nick = user.getNick();
final SpannableString messageWithBoldNick = new SpannableString(nick + ": " + message);
messageWithBoldNick.setSpan(new StyleSpan(Typeface.BOLD), 0, nick.length() + 1, 0);
return messageWithBoldNick;
}
private void addMainChatMessageToList(final CharSequence latestMessage) {
messages.add(latestMessage);
messageCount++;
}
private void addPrivateMessageToList(final User user, final String message) {
Collection<String> userMessages = privateMessages.get(user);
if (userMessages == null) {
userMessages = new CircularFifoQueue<>(MAX_MESSAGES);
privateMessages.put(user, userMessages);
}
userMessages.add(message);
final Integer userCount = privateMessageCount.get(user);
if (userCount == null) {
privateMessageCount.put(user, 1);
} else {
privateMessageCount.put(user, userCount + 1);
}
}
public void resetAllNotifications() {
notificationManager.cancel(MESSAGE_NOTIFICATION_ID);
cancelPrivateChatNotifications();
messages.clear();
privateMessages.clear();
messageCount = 0;
privateMessageCount.clear();
}
private void cancelPrivateChatNotifications() {
final Set<User> users = privateMessages.keySet();
for (final User user : users) {
notificationManager.cancel(getNotificationIdForUser(user));
}
}
public void resetPrivateChatNotification(final User user) {
privateMessages.remove(user);
privateMessageCount.remove(user);
notificationManager.cancel(getNotificationIdForUser(user));
}
private NotificationCompat.InboxStyle fillMainChatInbox() {
final NotificationCompat.InboxStyle inboxStyle = new NotificationCompat.InboxStyle();
for (final CharSequence msg : messages) {
inboxStyle.addLine(msg);
}
inboxStyle.setSummaryText(context.getString(R.string.notification_new_message));
return inboxStyle;
}
private NotificationCompat.Style fillPrivateChatInbox(final User user) {
final NotificationCompat.InboxStyle inboxStyle = new NotificationCompat.InboxStyle();
final Collection<String> userMessages = privateMessages.get(user);
if (userMessages != null) {
for (final String msg : userMessages) {
inboxStyle.addLine(msg);
}
inboxStyle.setSummaryText(context.getString(R.string.notification_new_private_message));
}
return inboxStyle;
}
private int getNotificationIdForUser(final User user) {
return MESSAGE_NOTIFICATION_ID + user.getCode();
}
private PendingIntent createIntentForMainChat() {
return PendingIntent.getActivity(context, 0, new Intent(context, MainChatController.class), 0);
}
private PendingIntent createIntentForPrivateChat(final User user) {
final Intent privateChatIntent = new Intent(context, PrivateChatController.class);
privateChatIntent.putExtra("userCode", user.getCode());
privateChatIntent.setAction("openPrivateChat " + System.currentTimeMillis()); // Unique - to avoid it being cached
return PendingIntent.getActivity(context, 0, privateChatIntent, 0);
}
public boolean isMainChatActivity() {
return messageCount > 0;
}
public boolean isPrivateChatActivity() {
return !privateMessageCount.isEmpty();
}
}