/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License") +  you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */
package org.apache.openmeetings.remote;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;

import org.apache.openmeetings.data.user.UserManager;
import org.apache.openmeetings.data.whiteboard.EmoticonsManager;
import org.apache.openmeetings.db.dao.room.RoomDao;
import org.apache.openmeetings.db.dao.server.ISessionManager;
import org.apache.openmeetings.db.entity.room.Client;
import org.apache.openmeetings.db.entity.room.Room;
import org.apache.openmeetings.remote.red5.ScopeApplicationAdapter;
import org.apache.openmeetings.remote.util.SessionVariablesUtil;
import org.apache.openmeetings.util.OpenmeetingsVariables;
import org.apache.openmeetings.util.stringhandlers.ChatString;
import org.red5.logging.Red5LoggerFactory;
import org.red5.server.api.IClient;
import org.red5.server.api.IConnection;
import org.red5.server.api.Red5;
import org.red5.server.api.service.IPendingServiceCall;
import org.red5.server.api.service.IPendingServiceCallback;
import org.red5.server.api.service.IServiceCapableConnection;
import org.slf4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;

/**
 * 
 * @author sebawagner
 *
 */
public class ChatService implements IPendingServiceCallback {
	private static final Logger log = Red5LoggerFactory.getLogger(ChatService.class, OpenmeetingsVariables.webAppRootKey);
	
	@Autowired
	private ScopeApplicationAdapter scopeApplicationAdapter;
	@Autowired
	private ISessionManager sessionManager = null;
	@Autowired
	private EmoticonsManager emoticonsManager;
	@Autowired
	private RoomDao roomDao;
	@Autowired
	private UserManager userManager;
	
	//number of items in the chat room history
	private static final int chatRoomHistory = 50;
	
	private static LinkedHashMap<Long,List<HashMap<String,Object>>> myChats = new LinkedHashMap<Long,List<HashMap<String,Object>>>();
	
	private String parseDateAsTimeString() {
		Calendar cal=Calendar.getInstance();
		
		int h = cal.get(Calendar.HOUR_OF_DAY);
		int m = cal.get(Calendar.MINUTE);

		String str_h,str_m;
		if (h<10) 
			str_h = "0"+Integer.toString(h);
		else
			str_h = Integer.toString(h);

		if (m<10) 
			str_m = "0"+Integer.toString(m);
		else
			str_m = Integer.toString(m);
		
		return str_h+':'+str_m;
	}

	public void sendChatMessage(String message) {
		IConnection current = Red5.getConnectionLocal();
		Client client = sessionManager.getClientByStreamId(current.getClient().getId(), null);
		List<String> msg = new ArrayList<String>();
		msg.add("chat"); //'privatechat'
		msg.add(""); //date-time
		msg.add("newtextmessage");
		msg.add(client.getUsername());
		msg.add(message);
		msg.add(client.getUsercolor());
		msg.add(client.getPublicSID()); //om[6] = parent.parent.isPrivate ? parent.parent.parent.refObj.publicSID : canvas.publicSID;
		msg.add("false");// canvas.isrtl;
		msg.add("" + client.getUser_id());
		Room room = roomDao.get(client.getRoom_id());
		msg.add("" + (room.getChatModerated() && !(client.getIsMod() || client.getIsSuperModerator())));
		sendMessageWithClient(msg);
	}
	
	/**
	 * sends a Chat-Message
	 * to all members of the Chatroom
	 * and all additional users (waitng for a free entry for example)
	 * 
	 * @param newMessage
	 * @return - 1 in case of success, -1 otherwise
	 */
	@SuppressWarnings("unchecked")
	public int sendMessageWithClient(Object newMessage) {
		try {
			IConnection current = Red5.getConnectionLocal();
			Client currentClient = sessionManager.getClientByStreamId(current.getClient().getId(), null);
			Long room_id = currentClient.getRoom_id();			
			log.debug("room_id: " + room_id);
			
			if (room_id == null) {
				return 1; //TODO weird
			}
			Room room = roomDao.get(room_id);
			@SuppressWarnings("rawtypes")
			ArrayList messageMap = (ArrayList) newMessage;
			// adding delimiter space, cause otherwise an emoticon in the last
			// string would not be found
			String messageText = messageMap.get(4) + " ";
			LinkedList<String[]> parsedStringObjects = ChatString.parseChatString(messageText, emoticonsManager.getEmotfilesList(), room.getAllowFontStyles());
			// log.error("parsedStringObjects"+parsedStringObjects.size());
			log.debug("size:" + messageMap.size());
			messageMap.add(parsedStringObjects);
			newMessage = messageMap;			

			boolean needModeration = Boolean.valueOf("" + messageMap.get(9));
			List<HashMap<String, Object>> myChatList = myChats.get(room_id);
			if (myChatList == null) myChatList = new LinkedList<HashMap<String, Object>>();
			
			HashMap<String, Object> hsm = new HashMap<String, Object>();
			hsm.put("message", newMessage);
			String publicSID = "" + messageMap.get(6);
			if (!publicSID.equals(currentClient.getPublicSID())) {
				hsm.put("client", sessionManager.getClientByPublicSID("" + messageMap.get(6), false, null));
				//need to remove unconfirmed chat message if any
				for (int i = myChatList.size() - 1; i > -1; --i) {
					Client msgClient = (Client)myChatList.get(i).get("client");
					@SuppressWarnings("rawtypes")
					List msgList = (List)myChatList.get(i).get("message");
					if (publicSID.equals(msgClient.getPublicSID())
						&& ("" + msgList.get(4)).equals(messageMap.get(4))
						&& ("" + msgList.get(1)).equals(messageMap.get(1))
						&& Boolean.valueOf("" + msgList.get(9))) {
						myChatList.remove(i);
						break;
					}
				}
				
			} else {
				// add server time
				messageMap.set(1, parseDateAsTimeString());
				hsm.put("client", currentClient);
			}

			if (myChatList.size() == chatRoomHistory) myChatList.remove(0);
			myChatList.add(hsm);
			myChats.put(room_id, myChatList);
			log.debug("SET CHATROOM: " + room_id);

			//broadcast to everybody in the room/domain
			for (IConnection conn : current.getScope().getClientConnections()) {
				if (conn != null) {
					if (conn instanceof IServiceCapableConnection) {
						
						Client rcl = this.sessionManager.getClientByStreamId(conn.getClient().getId(), null);
						
						if (rcl == null) {
							continue;
						}
						if (rcl.getIsAVClient()) {
							continue;
						}
						if (rcl.getIsScreenClient() != null && rcl.getIsScreenClient()) {
    						continue;
    					}
						if (needModeration && Boolean.TRUE != rcl.getIsMod() && Boolean.TRUE != rcl.getIsSuperModerator()) {
							continue;
						}
						((IServiceCapableConnection) conn).invoke("sendVarsToMessageWithClient",new Object[] { hsm }, this);
    			 	}
    			}
			}
		} catch (Exception err) {
			log.error("[ChatService sendMessageWithClient] ",err);
			return -1;
		}
		return 1;
	}

	//FIXME copy/past need to be removed
	@SuppressWarnings("unchecked")
	public int sendMessageWithClientByPublicSID(Object newMessage, String publicSID) {
		try {
			IConnection current = Red5.getConnectionLocal();
			Client currentClient = this.sessionManager.getClientByStreamId(current.getClient().getId(), null);
			Long room_id = currentClient.getRoom_id();
			Room room = roomDao.get(room_id);
			log.debug("room_id: " + room_id);

			@SuppressWarnings("rawtypes")
			ArrayList messageMap = (ArrayList) newMessage;
			// adding delimiter space, cause otherwise an emoticon in the last
			// string would not be found
			String messageText = messageMap.get(4).toString() + " ";
			// add server time
			messageMap.set(1, parseDateAsTimeString());
			LinkedList<String[]> parsedStringObjects = ChatString.parseChatString(messageText, emoticonsManager.getEmotfilesList(), room.getAllowFontStyles());
			// log.error("parsedStringObjects"+parsedStringObjects.size());
			log.debug("size:" + messageMap.size());
			messageMap.add(parsedStringObjects);
			newMessage = messageMap;

			HashMap<String, Object> hsm = new HashMap<String, Object>();
			hsm.put("client", currentClient);
			hsm.put("message", newMessage);

			// broadcast to everybody in the room/domain
			for (IConnection conn : current.getScope().getClientConnections()) {
				if (conn != null) {
					if (conn instanceof IServiceCapableConnection) {
						IClient client = conn.getClient();
						if (SessionVariablesUtil.isScreenClient(client)) {
							// screen sharing clients do not receive events
							continue;
						} else if (SessionVariablesUtil.isAVClient(client)) {
							// AVClients or potential AVClients do not receive events
							continue;
						}

						if (SessionVariablesUtil.getPublicSID(client).equals(publicSID)
								|| SessionVariablesUtil.getPublicSID(client).equals(
										currentClient.getPublicSID())) {
							((IServiceCapableConnection) conn).invoke(
								"sendVarsToMessageWithClient",
									new Object[] { hsm }, this);
						}
					}
				}
			}
		} catch (Exception err) {
			log.error("[ChatService sendMessageWithClient] ", err);
			return -1;
		}
		return 1;
	}

	public List<HashMap<String,Object>> clearChat() {
		try {
			IConnection current = Red5.getConnectionLocal();
			Client currentClient = this.sessionManager.getClientByStreamId(current.getClient().getId(), null);
			Long room_id = currentClient.getRoom_id();
			
			Long chatroom = room_id;
			log.debug("### GET CHATROOM: "+chatroom);
			
			List<HashMap<String,Object>> myChatList = myChats.get(chatroom);
			myChatList = new LinkedList<HashMap<String,Object>>();
			
			myChats.put(chatroom,myChatList);
			
			HashMap<String,Object> hsm = new HashMap<String,Object>();
			
			scopeApplicationAdapter.sendMessageToCurrentScope("clearChatContent", hsm, true);
			
			return myChatList;
			
		} catch (Exception err) {
			log.error("[clearChat] ",err);
			return null;
		}
	}
	
	public List<HashMap<String,Object>> getRoomChatHistory() {
		try {
			IConnection current = Red5.getConnectionLocal();
			Client currentClient = this.sessionManager.getClientByStreamId(current.getClient().getId(), null);
			Long room_id = currentClient.getRoom_id();
			
			log.debug("GET CHATROOM: " + room_id);
			
			List<HashMap<String,Object>> myChatList = myChats.get(room_id);
			if (myChatList==null) myChatList = new LinkedList<HashMap<String,Object>>();
			
			if (Boolean.TRUE != currentClient.getIsMod() && Boolean.TRUE != currentClient.getIsSuperModerator()) {
				//current user is not moderator, chat history need to be filtered
				List<HashMap<String,Object>> tmpChatList = new LinkedList<HashMap<String,Object>>(myChatList);
				for (int i = tmpChatList.size() - 1; i > -1; --i) {
					@SuppressWarnings("rawtypes")
					List msgList = (List)tmpChatList.get(i).get("message");
					if (Boolean.valueOf("" + msgList.get(9))) { //needModeration
						tmpChatList.remove(i);
					}
				}
				myChatList = tmpChatList;
			}
			
			return myChatList;
		} catch (Exception err) {
			log.error("[getRoomChatHistory] ",err);
			return null;
		}
	}
	
	/**
	 * gets the chat history by string for non-conference-clients
	 * 
	 * @param room_id
	 * @return - chat history of the room given, null in case of exception
	 */
	public List<HashMap<String,Object>> getRoomChatHistoryByString(Long room_id) {
		try {
			
			Long chatroom = room_id;
			log.debug("GET CHATROOM: "+chatroom);
			
			List<HashMap<String,Object>> myChatList = myChats.get(chatroom);
			if (myChatList==null) myChatList = new LinkedList<HashMap<String,Object>>();	
			
			return myChatList;
		} catch (Exception err) {
			log.error("[getRoomChatHistory] ",err);
			return null;
		}
	}	
	
	public void resultReceived(IPendingServiceCall arg0) {
		// TODO Auto-generated method stub
		log.error("resultReceived ChatService "+arg0);
	}
	
	public LinkedList<LinkedList<String>> getAllPublicEmoticons(){
		try {
			LinkedList<LinkedList<String>> publicemotes = new LinkedList<LinkedList<String>>();
			LinkedList<LinkedList<String>> allEmotes = emoticonsManager.getEmotfilesList();
			for (Iterator<LinkedList<String>> iter = allEmotes.iterator();iter.hasNext();){
				LinkedList<String> emot = iter.next();
				LinkedList<String> emotPub = new LinkedList<String>();
				if (emot.get((emot.size()-1)).equals("y")){
					emotPub.add(emot.get(0));
					emotPub.add(emot.get(1).replace("\\", ""));
					if (emot.size()>4) {
						emotPub.add(emot.get(2).replace("\\", ""));
						emotPub.add(emot.get(3));
						emotPub.add(emot.get(4));
					} else {
						emotPub.add(emot.get(2));
						emotPub.add(emot.get(3));
					}
					publicemotes.add(emotPub);
				}
			}
			return publicemotes;
		} catch (Exception err) {
			log.error("[getAllPublicEmoticons] ",err);
			return null;
		}
	}
	
}
