/*
 * 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.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;
	
	//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;
		}
	}
	
}
