/*
 * 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.openmeetings.app.remote.red5;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.openmeetings.app.OpenmeetingsVariables;
import org.openmeetings.app.conference.session.RoomClient;
import org.openmeetings.app.conference.whiteboard.BrowserStatus;
import org.openmeetings.app.conference.whiteboard.RoomStatus;
import org.openmeetings.app.conference.whiteboard.WhiteboardManagement;
import org.openmeetings.app.data.basic.Configurationmanagement;
import org.openmeetings.app.data.basic.Sessionmanagement;
import org.openmeetings.app.data.calendar.daos.MeetingMemberDaoImpl;
import org.openmeetings.app.data.calendar.management.AppointmentLogic;
import org.openmeetings.app.data.conference.Roommanagement;
import org.openmeetings.app.data.logs.ConferenceLogDaoImpl;
import org.openmeetings.app.data.user.Usermanagement;
import org.openmeetings.app.data.user.dao.UsersDaoImpl;
import org.openmeetings.app.persistence.beans.basic.Configuration;
import org.openmeetings.app.persistence.beans.calendar.Appointment;
import org.openmeetings.app.persistence.beans.calendar.MeetingMember;
import org.openmeetings.app.persistence.beans.rooms.Rooms;
import org.openmeetings.app.persistence.beans.user.Users;
import org.openmeetings.app.remote.FLVRecorderService;
import org.openmeetings.app.remote.WhiteBoardService;
import org.openmeetings.utils.math.CalendarPatterns;
import org.red5.client.net.rtmp.ClientExceptionHandler;
import org.red5.logging.Red5LoggerFactory;
import org.red5.server.adapter.ApplicationAdapter;
import org.red5.server.api.IClient;
import org.red5.server.api.IConnection;
import org.red5.server.api.Red5;
import org.red5.server.api.scope.IBasicScope;
import org.red5.server.api.scope.IBroadcastScope;
import org.red5.server.api.scope.IScope;
import org.red5.server.api.scope.ScopeType;
import org.red5.server.api.service.IPendingServiceCall;
import org.red5.server.api.service.IPendingServiceCallback;
import org.red5.server.api.service.IServiceCapableConnection;
import org.red5.server.api.stream.IBroadcastStream;
import org.red5.server.api.stream.IStreamListener;
import org.red5.server.api.stream.IStreamPacket;
import org.red5.server.net.rtmp.event.IRTMPEvent;
import org.red5.server.stream.StreamingProxy;
import org.red5.server.stream.message.RTMPMessage;
import org.slf4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;

public class ScopeApplicationAdapter extends ApplicationAdapter implements
		IPendingServiceCallback {

	private static final Logger log = Red5LoggerFactory.getLogger(
			ScopeApplicationAdapter.class,
			OpenmeetingsVariables.webAppRootKey);

	@Autowired
	private ClientListManager clientListManager;
	@Autowired
	private EmoticonsManager emoticonsManager;
	@Autowired
	private WhiteBoardService whiteBoardService;
	@Autowired
	private FLVRecorderService flvRecorderService;
	@Autowired
	private Configurationmanagement cfgManagement;
	@Autowired
	private AppointmentLogic appointmentLogic;
	@Autowired
	private Sessionmanagement sessionManagement;
	@Autowired
	private Usermanagement userManagement;
	@Autowired
	private Roommanagement roommanagement;
	@Autowired
	private ConferenceLogDaoImpl conferenceLogDao;
	@Autowired
	private UsersDaoImpl usersDao;
	@Autowired
	private MeetingMemberDaoImpl meetingMemberDao;

    private Map<String, StreamingProxy> streamingProxyMap = new HashMap<String, StreamingProxy>();
	// This is the Folder where all executables are written
	// for windows platform
	public static String batchFileDir = "webapps" + File.separatorChar + "ROOT"
			+ File.separatorChar + "jod" + File.separatorChar;
	public static String lineSeperator = System.getProperty("line.separator");

	// The Global WebApp Path
	public static String webAppPath = "";
	public static String configDirName = "conf";
	public static String profilesPrefix = "profile_";

	public static String configKeyCryptClassName = null;
	public static Boolean whiteboardDrawStatus = null;
	
	private static long broadCastCounter = 0;
	public static boolean initComplete = false;

	public synchronized void resultReceived(IPendingServiceCall arg0) {
		// TODO Auto-generated method stub
	}

	@Override
	public synchronized boolean appStart(IScope scope) {
		try {
			webAppPath = scope.getResource("/").getFile().getAbsolutePath();
			batchFileDir = webAppPath + File.separatorChar + OpenmeetingsVariables.STREAMS_DIR
					+ File.separatorChar;

			log.debug("webAppPath : " + webAppPath);
			log.debug("batchFileFir : " + batchFileDir);

			// Only load this Class one time
			// Initially this value might by empty, because the DB is empty yet
			Configuration conf = cfgManagement.getConfKey(3, "crypt_ClassName");
			if (conf != null) {
				ScopeApplicationAdapter.configKeyCryptClassName = conf
						.getConf_value();
			}

			// init your handler here

			// The scheduled Jobs did go into the Spring-Managed Beans, see
			// schedulerJobs.service.xml

			// Spring Definition does not work here, its too early, Instance is
			// not set yet
			emoticonsManager.loadEmot(scope);

			for (String scopeName : scope.getScopeNames()) {
				log.debug("scopeName :: " + scopeName);
			}

			ScopeApplicationAdapter.initComplete = true;

			clientListManager.removeAllClients();

			// OpenXGHttpClient.getInstance().openSIPgUserCreateTest();
			// OpenXGWrapperClient.getInstance().testConnection();
			// OpenXGClient.getInstance().testConnection();
			// ServerSocketMinaProcess serverSocketMinaProcess = new
			// ServerSocketMinaProcess();

			// serverSocketMinaProcess.doInitSocket();

		} catch (Exception err) {
			log.error("[appStart]", err);
		}
		return true;
	}

	@Override
	public boolean roomConnect(IConnection conn, Object[] params) {
		log.debug("roomConnect : ");

		try {

			IServiceCapableConnection service = (IServiceCapableConnection) conn;
			String streamId = conn.getClient().getId();
			
			boolean isAVClient = false;
			if (params.length == 1) {
				isAVClient = Boolean.parseBoolean(params[0].toString());
			}

			log.debug("### Client connected to OpenMeetings, register Client StreamId: "
					+ streamId + " scope " + conn.getScope().getName()+ " isAVClient "+isAVClient);
			log.debug("params "+params);

			// Set StreamId in Client
			service.invoke("setId", new Object[] { streamId }, this);

			String swfURL = "";
			if (conn.getConnectParams().get("swfUrl") != null) {
				swfURL = conn.getConnectParams().get("swfUrl").toString();
			}

			RoomClient rcm = this.clientListManager.addClientListItem(streamId,
					conn.getScope().getName(), conn.getRemotePort(),
					conn.getRemoteAddress(), swfURL, isAVClient);

			// Log the User
			conferenceLogDao.addConferenceLog("ClientConnect",
					rcm.getUser_id(), streamId, null, rcm.getUserip(),
					rcm.getScope(), rcm.getExternalUserId(),
					rcm.getExternalUserType(), rcm.getMail(),
					rcm.getFirstname(), rcm.getLastname());

		} catch (Exception err) {
			log.error("roomJoin", err);
		}
		return true;
	}

	@SuppressWarnings({ "rawtypes", "unchecked" })
	public synchronized Map screenSharerAction(Map map) {
		try {

			IConnection current = Red5.getConnectionLocal();

			RoomClient currentClient = this.clientListManager
					.getClientByStreamId(current.getClient().getId());

			Map returnMap = new HashMap();
			returnMap.put("result", "stopAll");

			log.debug("-----------  ");

			if (currentClient != null) {

				if (Boolean.valueOf(map.get("stopStreaming").toString())) {
					log.debug("start streamPublishStart Is Screen Sharing -- Stop ");
					
					//Send message to all users
					syncMessageToCurrentScope("stopRed5ScreenSharing", currentClient, false);

					if (currentClient.isStartRecording()) {
						returnMap.put("result", "stopSharingOnly");
					}

					currentClient.setStartStreaming(false);
					currentClient.setScreenPublishStarted(false);

					clientListManager.updateClientByStreamId(
							currentClient.getStreamid(), currentClient);
				}
				if (Boolean.valueOf(map.get("stopRecording").toString())) {
					if (currentClient.isStartStreaming()) {
						returnMap.put("result", "stopRecordingOnly");
					}
					
					//Send message to all users
					syncMessageToCurrentScope("stopRecordingMessage", currentClient, false);

					flvRecorderService.stopRecordAndSave(
							current.getScope(), currentClient, null);

					currentClient.setStartRecording(false);
					currentClient.setIsRecording(false);

					clientListManager.updateClientByStreamId(
							currentClient.getStreamid(), currentClient);
				}
				if (Boolean.valueOf(map.get("stopPublishing").toString())) {
					streamPublishingStop();
					if (currentClient.getIsScreenClient() && currentClient.isStartStreaming()) {
						returnMap.put("result", "stopPublishingOnly");
					}
				}
			}
			return returnMap;
		} catch (Exception err) {
			log.error("[screenSharerAction]", err);
		}
		return null;
	}

	public List<RoomClient> checkRed5ScreenSharing() {
		try {
			IConnection current = Red5.getConnectionLocal();
			String streamid = current.getClient().getId();

			log.debug("checkScreenSharing -2- " + streamid);

			List<RoomClient> screenSharerList = new LinkedList<RoomClient>();

			RoomClient currentClient = this.clientListManager
					.getClientByStreamId(streamid);

			HashMap<String, RoomClient> roomList = this.clientListManager
					.getClientListByRoomAll(currentClient.getRoom_id());

			for (Iterator<String> iter = roomList.keySet().iterator(); iter
					.hasNext();) {

				RoomClient rcl = roomList.get(iter.next());

				if (rcl.isStartStreaming()) {
					screenSharerList.add(rcl);
				}

			}

			return screenSharerList;

		} catch (Exception err) {
			log.error("[checkScreenSharing]", err);
		}
		return null;
	}

	@SuppressWarnings({ "rawtypes", "unchecked" })
	public synchronized Map setConnectionAsSharingClient(Map map) {
		try {

			IConnection current = Red5.getConnectionLocal();
			// IServiceCapableConnection service = (IServiceCapableConnection)
			// current;

			log.debug("### setConnectionAsSharingClient: ");

			RoomClient currentClient = this.clientListManager
					.getClientByStreamId(current.getClient().getId());

			if (currentClient != null) {

				boolean startRecording = Boolean.valueOf(map.get(
						"startRecording").toString());
				boolean startStreaming = Boolean.valueOf(map.get(
						"startStreaming").toString());

				currentClient.setRoom_id(Long.parseLong(current.getScope()
						.getName()));

				// Set this connection to be a RTMP-Java Client
				currentClient.setIsScreenClient(true);
				currentClient.setUser_id(Long.parseLong(map.get("user_id")
						.toString()));

				if (startStreaming) {
					currentClient.setStartStreaming(true);
				}

				if (startRecording) {
					currentClient.setStartRecording(true);
				}

				currentClient.setOrganization_id(Long.parseLong(map.get(
						"organization_id").toString()));

				this.clientListManager.updateClientByStreamId(current
						.getClient().getId(), currentClient);

				Map returnMap = new HashMap();
				returnMap.put("alreadyPublished", false);

				// if is already started screen sharing, then there is no need
				// to start it again
				if (currentClient.isScreenPublishStarted()) {
					returnMap.put("alreadyPublished", true);
				}

				currentClient.setVX(Integer.parseInt(map.get("screenX")
						.toString()));
				currentClient.setVY(Integer.parseInt(map.get("screenY")
						.toString()));
				currentClient.setVWidth(Integer.parseInt(map.get("screenWidth")
						.toString()));
				currentClient.setVHeight(Integer.parseInt(map.get(
						"screenHeight").toString()));

				log.debug("screen x,y,width,height " + currentClient.getVX()
						+ " " + currentClient.getVY() + " "
						+ currentClient.getVWidth() + " "
						+ currentClient.getVHeight());

				log.debug("publishName :: " + map.get("publishName"));

				currentClient.setStreamPublishName(map.get("publishName")
						.toString());

				RoomClient currentScreenUser = this.clientListManager
						.getClientByPublicSID(currentClient
								.getStreamPublishName(), false);

				currentClient.setFirstname(currentScreenUser.getFirstname());
				currentClient.setLastname(currentScreenUser.getLastname());

				// This is duplicated, but its not sure that in the meantime
				// somebody requests this Client Object Info
				this.clientListManager.updateClientByStreamId(current
						.getClient().getId(), currentClient);

				if (startStreaming) {
					returnMap.put("modus", "startStreaming");

					log.debug("start streamPublishStart Is Screen Sharing ");
					
					//Send message to all users
					syncMessageToCurrentScope("newRed5ScreenSharing", currentClient, false);
				} else if (startRecording) {
					returnMap.put("modus", "startRecording");

					String recordingName = "Recording "
							+ CalendarPatterns
									.getDateWithTimeByMiliSeconds(new Date());

					flvRecorderService.recordMeetingStream(recordingName, "", false);
				} else if (Boolean.valueOf(map.get("startPublishing").toString())) {
					if (streamPublishingStart("" + map.get("publishingHost")
						, "" + map.get("publishingApp")
						, "" + map.get("publishingId")))
					{
						returnMap.put("modus", "startPublishing");
					}
				}

				return returnMap;

			} else {
				throw new Exception("Could not find Screen Sharing Client "
						+ current.getClient().getId());
			}

		} catch (Exception err) {
			log.error("[setConnectionAsSharingClient]", err);
		}
		return null;
	}

    public synchronized List<Integer> listRoomBroadcast() {
        List<Integer> broadcastList = new ArrayList<Integer>();
        IConnection current = Red5.getConnectionLocal();
        String streamid = current.getClient().getId();
        Collection<Set<IConnection>> conCollection = current.getScope().getConnections();
        for (Set<IConnection> conset : conCollection) {
            for (IConnection conn : conset) {
                if (conn != null) {
                    RoomClient rcl = this.clientListManager
                            .getClientByStreamId(conn
                                    .getClient().getId());
                    if (rcl == null) {
                        // continue;
                    } else if (rcl.getIsScreenClient() != null
                            && rcl.getIsScreenClient()) {
                        // continue;
                    } else {
                        if (!streamid.equals(rcl.getStreamid())) {
                            // It is not needed to send back
                            // that event to the actuall
                            // Moderator
                            // as it will be already triggered
                            // in the result of this Function
                            // in the Client
                            broadcastList.add(Long.valueOf(rcl.getBroadCastID()).intValue());
                        }
                    }
                }
            }
        }
        return broadcastList;
    }


	/**
	 * this function is invoked directly after initial connecting
	 * 
	 * @return
	 */
	public synchronized String getPublicSID() {
		IConnection current = Red5.getConnectionLocal();
		RoomClient currentClient = this.clientListManager
				.getClientByStreamId(current.getClient().getId());
		currentClient.setIsAVClient(false);
		clientListManager.updateClientByStreamId(current.getClient().getId(),
				currentClient);
		return currentClient.getPublicSID();
	}

	/**
	 * this function is invoked after a reconnect
	 * 
	 * @param newPublicSID
	 */
	public synchronized Boolean overwritePublicSID(String newPublicSID) {
		try {
			IConnection current = Red5.getConnectionLocal();
			RoomClient currentClient = this.clientListManager
					.getClientByStreamId(current.getClient().getId());
			if (currentClient == null) {
				return false;
			}
			currentClient.setPublicSID(newPublicSID);
			this.clientListManager.updateClientByStreamId(current.getClient()
					.getId(), currentClient);
			return true;
		} catch (Exception err) {
			log.error("[overwritePublicSID]", err);
		}
		return null;
	}

	/**
	 * Logic must be before roomDisconnect cause otherwise you cannot throw a
	 * message to each one
	 * 
	 */
	@Override
	public void roomLeave(IClient client, IScope room) {
		try {

			log.debug("roomLeave " + client.getId() + " "
					+ room.getClients().size() + " " + room.getContextPath()
					+ " " + room.getName());

			RoomClient currentClient = this.clientListManager
					.getClientByStreamId(client.getId());

			// The Room Client can be null if the Client left the room by using
			// logicalRoomLeave
			if (currentClient != null) {
				log.debug("currentClient IS NOT NULL");
				this.roomLeaveByScope(currentClient, room, true);
			}

		} catch (Exception err) {
			log.error("[roomLeave]", err);
		}
	}

	/**
	 * this means a user has left a room but only logically, he didn't leave the
	 * app he just left the room
	 * 
	 * FIXME: Is this really needed anymore if you re-connect to another scope?
	 * 
	 * Exit Room by Application
	 * 
	 */
	public synchronized void logicalRoomLeave() {
		log.debug("logicalRoomLeave ");
		try {
			IConnection current = Red5.getConnectionLocal();
			String streamid = current.getClient().getId();

			log.debug(streamid + " is leaving");

			RoomClient currentClient = this.clientListManager
					.getClientByStreamId(streamid);

			this.roomLeaveByScope(currentClient, current.getScope(), true);

		} catch (Exception err) {
			log.error("[logicalRoomLeave]", err);
		}
	}

	/**
	 * Removes the Client from the List, stops recording, adds the Room-Leave
	 * event to running recordings, clear Polls and removes Client from any list
	 * 
	 * This function is kind of private/protected as the client won't be able 
	 * to call it with proper values.
	 * 
	 * @param currentClient
	 * @param currentScope
	 */
	public synchronized void roomLeaveByScope(RoomClient currentClient,
			IScope currentScope, boolean removeUserFromSessionList) {
		try {

			log.debug("currentClient " + currentClient);
			log.debug("currentScope " + currentScope);
			// log.debug("currentClient "+currentClient.getRoom_id());

			Long room_id = currentClient.getRoom_id();

			// Log the User
			conferenceLogDao.addConferenceLog("roomLeave",
					currentClient.getUser_id(), currentClient.getStreamid(),
					room_id, currentClient.getUserip(), "",
					currentClient.getExternalUserId(),
					currentClient.getExternalUserType(),
					currentClient.getMail(), currentClient.getFirstname(),
					currentClient.getLastname());

			// Remove User from Sync List's
			if (room_id != null) {
				this.whiteBoardService.removeUserFromAllLists(currentScope,
						currentClient);
			}

			log.debug("removing USername " + currentClient.getUsername() + " "
					+ currentClient.getConnectedSince() + " streamid: "
					+ currentClient.getStreamid());

			// stop and save any recordings
			if (currentClient.getIsRecording()) {
				log.debug("*** roomLeave Current Client is Recording - stop that");
				// StreamService.stopRecordAndSave(currentScope,
				// currentClient.getRoomRecordingName(), currentClient);

				this.flvRecorderService.stopRecordAndSave(currentScope,
						currentClient, null);

				// set to true and overwrite the default one cause otherwise no
				// notification is send
				currentClient.setIsRecording(true);
			}

			// Notify all clients of the same currentScope (room) with domain
			// and room except the current disconnected cause it could throw an exception
			log.debug("currentScope " + currentScope);

			if (currentScope != null && currentScope.getConnections() != null) {
				// Notify Users of the current Scope
				Collection<Set<IConnection>> conCollection = currentScope
						.getConnections();
				for (Set<IConnection> conset : conCollection) {
					for (IConnection cons : conset) {
						if (cons != null) {
							if (cons instanceof IServiceCapableConnection) {

								log.debug("sending roomDisconnect to " + cons
										+ " client id "
										+ cons.getClient().getId());

								RoomClient rcl = this.clientListManager
										.getClientByStreamId(cons.getClient()
												.getId());

								/*
								 * Check if the Client does still exist on the
								 * list
								 */
								if (rcl != null) {

									/*
									 * Do not send back to sender, but actually
									 * all other clients should receive this
									 * message swagner 01.10.2009
									 */
									if (!currentClient.getStreamid().equals(
											rcl.getStreamid())) {
										
										// add Notification if another user isrecording
										log.debug("###########[roomLeave]");
										if (rcl.getIsRecording()) {
											log.debug("*** roomLeave Any Client is Recording - stop that");
											this.flvRecorderService
													.stopRecordingShowForClient(
															cons, currentClient);
										}
										
										//If the user was a avclient, we do not broadcast a message about that to everybody
										if (currentClient.getIsAVClient()) {
											continue;
										}
										
										if (rcl.getIsScreenClient() != null && rcl
												.getIsScreenClient()) {
											// screen sharing clients do not receive events
											continue;
										} else if (rcl.getIsAVClient()) {
											// AVClients or potential AVClients do not receive events
											continue;
										}
										
										// Send to all connected users
										((IServiceCapableConnection) cons)
												.invoke("roomDisconnect",
													new Object[] { currentClient },this);
										log.debug("sending roomDisconnect to " + cons);
									}
								} else {
									log.debug("For this StreamId: "
											+ cons.getClient().getId()
											+ " There is no Client in the List anymore");
								}
							}
						}
					}
				}
			}

			if (removeUserFromSessionList) {
				this.clientListManager.removeClient(currentClient.getStreamid());
			}
		} catch (Exception err) {
			log.error("[roomLeaveByScope]", err);
		}
	}

	/**
	 * This method handles the Event after a stream has been added all connected
	 * Clients in the same room will get a notification
	 * 
	 * @return void
	 * 
	 */
	@Override
	public synchronized void streamPublishStart(IBroadcastStream stream) {
		try {
			IConnection current = Red5.getConnectionLocal();
			String streamid = current.getClient().getId();
			RoomClient currentClient = this.clientListManager
					.getClientByStreamId(streamid);

			//We make a second object the has the reference to the object 
			//that we will use to send to all participents
			RoomClient clientObjectSendToSync = currentClient;
			
			// Notify all the clients that the stream had been started
			log.debug("start streamPublishStart broadcast start: "
					+ stream.getPublishedName() + " CONN " + current);

			// In case its a screen sharing we start a new Video for that
			if (currentClient.getIsScreenClient()) {

				currentClient.setScreenPublishStarted(true);

				this.clientListManager.updateClientByStreamId(current
						.getClient().getId(), currentClient);
			}
			//If its an audio/video client then send the session object with the full 
			//data to everybody
			else if (currentClient.getIsAVClient()) {
				clientObjectSendToSync = this.clientListManager.getClientByPublicSID(
											currentClient.getPublicSID(), false);
			}
			
			log.debug("newStream SEND: "+currentClient);

			// Notify all users of the same Scope
			// We need to iterate through the streams to catch if anybody is recording
			Collection<Set<IConnection>> conCollection = current.getScope()
					.getConnections();
			for (Set<IConnection> conset : conCollection) {
				for (IConnection conn : conset) {
					if (conn != null) {
						if (conn instanceof IServiceCapableConnection) {
							
							RoomClient rcl = this.clientListManager
									.getClientByStreamId(conn.getClient()
											.getId());
							
							if (rcl == null) {
								log.debug("RCL IS NULL newStream SEND");
								continue;
							}
							
							log.debug("check send to "+rcl);
							
							if (rcl.getPublicSID() == "") {
								log.debug("publicSID IS NULL newStream SEND");
								continue;
							}
							if (rcl.getIsRecording()) {
								log.debug("RCL getIsRecording newStream SEND");
								this.flvRecorderService
										.addRecordingByStreamId(current,
												streamid, currentClient,
												rcl.getFlvRecordingId());
							}
							if (rcl.getIsAVClient()) {
								log.debug("RCL getIsAVClient newStream SEND");
								continue;
							}
							if (rcl.getIsScreenClient() == null || rcl.getIsScreenClient()) {
								log.debug("RCL getIsScreenClient newStream SEND");
								continue;
							}
							
							if (rcl.getPublicSID().equals(currentClient.getPublicSID())) {
								log.debug("RCL publicSID is equal newStream SEND");
								continue;
							}
							
							log.debug("RCL SEND is equal newStream SEND "+rcl.getPublicSID()+" || "+rcl.getUserport());
								
							IServiceCapableConnection iStream = (IServiceCapableConnection) conn;
							iStream.invoke("newStream",
									new Object[] { clientObjectSendToSync },
									this);

						}
					}
				}
			}

		} catch (Exception err) {
			log.error("[streamPublishStart]", err);
		}
	}

	public IBroadcastScope getBroadcastScope(IScope scope, String name) {
		IBasicScope basicScope = scope.getBasicScope(ScopeType.BROADCAST, name);
		if (!(basicScope instanceof IBroadcastScope)) {
			return null;
		} else {
			return (IBroadcastScope) basicScope;
		}
	}

    public boolean streamPublishingStart(String host, String app, String id) {
    	final boolean[] result = {true};
		final IConnection conn = Red5.getConnectionLocal();
		RoomClient rc = clientListManager.getClientByStreamId(conn.getClient().getId());
		String publishName = rc.getStreamPublishName();
		
		if (rc.getIsScreenClient() && rc.isStartStreaming()) {
	        IScope scope = conn.getScope();
	        IBroadcastStream stream = getBroadcastStream(scope, publishName);
	        IBroadcastScope bsScope = getBroadcastScope(scope, publishName);
	        final StreamingProxy proxy = new StreamingProxy();
	        proxy.setHost(host);
	        proxy.setApp(app);
	        proxy.setPort(1935);
	        proxy.init();
	        proxy.setExceptionHandler(new ClientExceptionHandler() {
				public void handleException(Throwable throwable) {
					result[0] = false;
					HashMap<String, Object> params = new HashMap<String, Object>();
					params.put("stopPublishing", true);
					params.put("error", throwable.getMessage());
					((IServiceCapableConnection)conn).invoke(
						"screenSharerAction"
						, new Object[] { params }
						, ScopeApplicationAdapter.this);
				}
			});
	        bsScope.subscribe(proxy, null);
	        proxy.start(id, "live", null);
	        streamingProxyMap.put(publishName, proxy);
	        stream.addStreamListener(new IStreamListener() {
				public void packetReceived(IBroadcastStream stream, IStreamPacket packet) {
					try {
						RTMPMessage m = RTMPMessage.build((IRTMPEvent)packet, packet.getTimestamp());
				        proxy.pushMessage(null, m);
					} catch (Exception e) {
						log.error("Exception while sending proxy message", e);
					}
				}
			});
		}
		return result[0];
    }
    
    public void streamPublishingStop() {
		IConnection current = Red5.getConnectionLocal();
		RoomClient rc = clientListManager.getClientByStreamId(current.getClient().getId());
		String publishName = rc.getStreamPublishName();
		
		if (rc.getIsScreenClient() && publishName != null) {
	        IScope scope = current.getScope();
	        IBroadcastStream stream = getBroadcastStream(scope, publishName);
			StreamingProxy proxy = streamingProxyMap.remove(publishName);
			if (proxy != null) {
				proxy.stop();
				IBroadcastScope bsScope = getBroadcastScope(scope, stream.getPublishedName());
				if (bsScope != null) {
					bsScope.unsubscribe(proxy);
				}
			}
		}
    }
    
	/**
	 * This method handles the Event after a stream has been removed all
	 * connected Clients in the same room will get a notification
	 * 
	 * @return void
	 * 
	 */
	@Override
	public synchronized void streamBroadcastClose(IBroadcastStream stream) {

		// Notify all the clients that the stream had been closed
		log.debug("start streamBroadcastClose broadcast close: "
				+ stream.getPublishedName());
		try {
			streamPublishingStop();
			
			IConnection current = Red5.getConnectionLocal();
			RoomClient rcl = clientListManager.getClientByStreamId(current.getClient().getId());
			sendClientBroadcastNotifications(stream, "closeStream", rcl);
		} catch (Exception e) {
			log.error("[streamBroadcastClose]", e);
		}
	}

	/**
	 * This method handles the notification room-based
	 * 
	 * @return void
	 * 
	 */
	private synchronized void sendClientBroadcastNotifications(
			IBroadcastStream stream, String clientFunction, RoomClient rc) {
		try {

			// Store the local so that we do not send notification to ourself
			// back
			IConnection current = Red5.getConnectionLocal();
			String streamid = current.getClient().getId();
			RoomClient currentClient = this.clientListManager
					.getClientByStreamId(streamid);

			if (currentClient == null) {

				// In case the client has already left(kicked) this message
				// might be thrown later then the RoomLeave
				// event and the currentClient is already gone
				// The second Use-Case where the currentClient is maybe null is
				// if we remove the client because its a Zombie/Ghost

				return;

			}
			// Notify all the clients that the stream had been started
			log.debug("sendClientBroadcastNotifications: "
					+ stream.getPublishedName());
			log.debug("sendClientBroadcastNotifications : " + currentClient
					+ " " + currentClient.getStreamid());

			// Notify all clients of the same scope (room)
			Collection<Set<IConnection>> conCollection = current.getScope()
					.getConnections();
			for (Set<IConnection> conset : conCollection) {
				for (IConnection conn : conset) {
					if (conn != null) {
						if (conn instanceof IServiceCapableConnection) {
							if (conn.equals(current)) {
								// there is a Bug in the current implementation
								// of the appDisconnect
								if (clientFunction.equals("closeStream")) {
									RoomClient rcl = this.clientListManager
											.getClientByStreamId(conn
													.getClient().getId());
									if (clientFunction.equals("closeStream")
											&& rcl.getIsRecording()) {
										log.debug("*** stopRecordingShowForClient Any Client is Recording - stop that");
										// StreamService.stopRecordingShowForClient(conn,
										// currentClient,
										// rcl.getRoomRecordingName(), false);
										this.flvRecorderService
												.stopRecordingShowForClient(
														conn, currentClient);
									}
									// Don't notify current client
									current.ping();
								}
								continue;
							} else {
								RoomClient rcl = this.clientListManager
										.getClientByStreamId(conn.getClient()
												.getId());
								if (rcl != null) {
									if (rcl.getIsScreenClient() != null
											&& rcl.getIsScreenClient()) {
										// continue;
									} else {
										log.debug("is this users still alive? :"
												+ rcl);
										// conn.ping();
										IServiceCapableConnection iStream = (IServiceCapableConnection) conn;
										// log.info("IServiceCapableConnection ID "
										// + iStream.getClient().getId());
										iStream.invoke(clientFunction,
												new Object[] { rc }, this);
									}

									log.debug("sending notification to " + conn
											+ " ID: ");

									// if this close stream event then stop the
									// recording of this stream
									if (clientFunction.equals("closeStream")
											&& rcl.getIsRecording()) {
										log.debug("***  +++++++ ######## sendClientBroadcastNotifications Any Client is Recording - stop that");
										// StreamService.stopRecordingShowForClient(conn,
										// currentClient,
										// rcl.getRoomRecordingName(), false);
										this.flvRecorderService
												.stopRecordingShowForClient(
														conn, currentClient);
									}
								}

							}
						}
					}
				}
			}
		} catch (Exception err) {
			log.error("[sendClientBroadcastNotifications]", err);
		}
	}


	/**
	 * Adds a Moderator by its publicSID
	 * 
	 * @param publicSID
	 * @return
	 */
	public synchronized Long addModerator(String publicSID) {
		try {

			log.debug("*..*addModerator publicSID: " + publicSID);

			// String streamid = current.getClient().getId();

			RoomClient currentClient = this.clientListManager
					.getClientByPublicSID(publicSID, false);

			if (currentClient == null) {
				return -1L;
			}
			Long room_id = currentClient.getRoom_id();

			currentClient.setIsMod(true);
			// Put the mod-flag to true for this client
			this.clientListManager.updateClientByStreamId(
					currentClient.getStreamid(), currentClient);

			List<RoomClient> currentMods = this.clientListManager
					.getCurrentModeratorByRoom(room_id);
			
			//Send message to all users
			syncMessageToCurrentScope("setNewModeratorByList", currentMods, true);

		} catch (Exception err) {
			log.error("[addModerator]", err);
		}
		return -1L;
	}

	@SuppressWarnings("unchecked")
	public void setNewCursorPosition(Object item) {
		try {

			IConnection current = Red5.getConnectionLocal();
			String streamid = current.getClient().getId();
			RoomClient currentClient = this.clientListManager
					.getClientByStreamId(streamid);

			// log.debug("[setNewCursorPosition]"+item);

			@SuppressWarnings("rawtypes")
			Map cursor = (Map) item;
			cursor.put("streamPublishName",
					currentClient.getStreamPublishName());

			// log.debug("[setNewCursorPosition x]"+cursor.get("cursor_x"));
			// log.debug("[setNewCursorPosition y]"+cursor.get("cursor_y"));
			// log.debug("[setNewCursorPosition publicSID]"+cursor.get("publicSID"));

			// Notify all users of the same Scope
			Collection<Set<IConnection>> conCollection = current.getScope()
					.getConnections();
			for (Set<IConnection> conset : conCollection) {
				for (IConnection conn : conset) {
					if (conn != null) {
						if (conn instanceof IServiceCapableConnection) {
							if (conn.equals(current)) {
								continue;
							} else {
								RoomClient rcl = this.clientListManager
										.getClientByStreamId(conn.getClient()
												.getId());
								if (rcl == null) {
									// continue;
								} else if (rcl.getIsScreenClient() != null
										&& rcl.getIsScreenClient()) {
									// continue;
								} else {
									// log.debug("is this users still alive? :"+rcl);
									// Check if the Client is in the same room
									// and same domain
									IServiceCapableConnection iStream = (IServiceCapableConnection) conn;
									// log.info("IServiceCapableConnection ID "
									// + iStream.getClient().getId());
									iStream.invoke("newRed5ScreenCursor",
											new Object[] { cursor }, this);
									// log.debug("send Notification to");
								}
							}
						}
					}
				}
			}

		} catch (Exception err) {
			log.error("[setNewCursorPosition]", err);
		}
	}

	public synchronized Long removeModerator(String publicSID) {
		try {

			log.debug("*..*addModerator publicSID: " + publicSID);

			IConnection current = Red5.getConnectionLocal();
			// String streamid = current.getClient().getId();

			RoomClient currentClient = this.clientListManager
					.getClientByPublicSID(publicSID, false);

			if (currentClient == null) {
				return -1L;
			}
			Long room_id = currentClient.getRoom_id();

			currentClient.setIsMod(false);
			// Put the mod-flag to true for this client
			this.clientListManager.updateClientByStreamId(
					currentClient.getStreamid(), currentClient);

			List<RoomClient> currentMods = this.clientListManager
					.getCurrentModeratorByRoom(room_id);

			// Notify all clients of the same scope (room)
			Collection<Set<IConnection>> conCollection = current.getScope()
					.getConnections();
			for (Set<IConnection> conset : conCollection) {
				for (IConnection conn : conset) {
					if (conn != null) {
						RoomClient rcl = this.clientListManager
								.getClientByStreamId(conn.getClient().getId());
						if (rcl == null) {
							// continue;
						} else if (rcl.getIsScreenClient() != null
								&& rcl.getIsScreenClient()) {
							// continue;
						} else {
							log.debug("Send Flag to Client: "
									+ rcl.getUsername());
							if (conn instanceof IServiceCapableConnection) {
								((IServiceCapableConnection) conn).invoke(
										"setNewModeratorByList",
										new Object[] { currentMods }, this);
								log.debug("sending setNewModeratorByList to "
										+ conn);
							}
						}
					}
				}
			}

		} catch (Exception err) {
			log.error("[addModerator]", err);
		}
		return -1L;
	}

	public synchronized Long setBroadCastingFlag(String publicSID,
			boolean value, Integer interviewPodId) {
		try {

			log.debug("*..*setBroadCastingFlag publicSID: " + publicSID);

			IConnection current = Red5.getConnectionLocal();
			// String streamid = current.getClient().getId();

            RoomClient currentClient = this.clientListManager
					.getClientByPublicSID(publicSID, false);

			if (currentClient == null) {
				return -1L;
			}

			currentClient.setIsBroadcasting(value);
			currentClient.setInterviewPodId(interviewPodId);

            // Put the mod-flag to true for this client
		    this.clientListManager.updateClientByStreamId(
		    		currentClient.getStreamid(), currentClient);
		    
			// Notify all clients of the same scope (room)
			Collection<Set<IConnection>> conCollection = current.getScope()
					.getConnections();
			for (Set<IConnection> conset : conCollection) {
				for (IConnection conn : conset) {
					if (conn != null) {
						RoomClient rcl = this.clientListManager
								.getClientByStreamId(conn.getClient().getId());
						if (rcl == null) {
							continue;
						} else if (rcl.getIsScreenClient() != null
								&& rcl.getIsScreenClient()) {
							continue;
						} else if (rcl.getIsAVClient()) {
							continue;
						}
						
						log.debug("Send Flag to Client: "
								+ rcl.getUsername());
						if (conn instanceof IServiceCapableConnection) {
							((IServiceCapableConnection) conn).invoke(
									"setNewBroadCastingFlag",
									new Object[] { currentClient }, this);
							log.debug("sending setNewBroadCastingFlag to "
									+ conn);
						}
					}
				}
			}

		} catch (Exception err) {
			log.error("[setBroadCastingFlag]", err);
		}
		return -1L;
	}

	public synchronized Long giveExclusiveAudio(String publicSID) {
		try {

			log.debug("*..*giveExclusiveAudio publicSID: " + publicSID);

			IConnection current = Red5.getConnectionLocal();
			// String streamid = current.getClient().getId();

			RoomClient currentClient = this.clientListManager
					.getClientByPublicSID(publicSID, false);

			if (currentClient == null) {
				return -1L;
			}

			// Put the mod-flag to true for this client
			currentClient.setMicMuted(false);
			this.clientListManager.updateClientByStreamId(
					currentClient.getStreamid(), currentClient);

			// Notify all clients of the same scope (room)
			Collection<Set<IConnection>> conCollection = current.getScope()
					.getConnections();
			for (Set<IConnection> conset : conCollection) {
				for (IConnection conn : conset) {
					if (conn != null) {
						RoomClient rcl = this.clientListManager
								.getClientByStreamId(conn.getClient().getId());
						if (rcl == null) {
							// continue;
						} else if (rcl.getIsScreenClient() != null
								&& rcl.getIsScreenClient()) {
							// continue;
						} else {
							if (rcl != currentClient) {
								rcl.setMicMuted(true);
								this.clientListManager.updateClientByStreamId(
										rcl.getStreamid(), rcl);
							}
							log.debug("Send Flag to Client: "
									+ rcl.getUsername());
							if (conn instanceof IServiceCapableConnection) {
								((IServiceCapableConnection) conn).invoke(
										"receiveExclusiveAudioFlag",
										new Object[] { currentClient }, this);
								log.debug("sending receiveExclusiveAudioFlag to "
										+ conn);
							}
						}
					}
				}
			}

		} catch (Exception err) {
			log.error("[giveExclusiveAudio]", err);
		}
		return -1L;
	}

	public synchronized Long switchMicMuted(String publicSID, boolean mute) {
		try {
			log.debug("*..*switchMicMuted publicSID: " + publicSID);

			RoomClient currentClient = this.clientListManager
					.getClientByPublicSID(publicSID, false);
			if (currentClient == null) {
				return -1L;
			}

			currentClient.setMicMuted(mute);
			this.clientListManager.updateClientByStreamId(
					currentClient.getStreamid(), currentClient);

			HashMap<Integer, Object> newMessage = new HashMap<Integer, Object>();
			newMessage.put(0, "updateMuteStatus");
			newMessage.put(1, currentClient);
			this.sendMessageWithClient(newMessage);

		} catch (Exception err) {
			log.error("[switchMicMuted]", err);
		}
		return 0L;
	}

    public synchronized Boolean getMicMutedByPublicSID(String publicSID) {
        try {
			RoomClient currentClient = this.clientListManager.getClientByPublicSID(publicSID, false);
			if (currentClient == null) {
				return true;
			}

			//Put the mod-flag to true for this client
            Boolean muted = currentClient.getMicMuted();
            if (null == muted) {
                muted = true;
            }

            return muted;
        } catch (Exception err) {
			log.error("[getMicMutedByPublicSID]",err);
		}
		return true;
    }

	/**
	 * Invoked by a User whenever he want to become moderator this is needed,
	 * cause if the room has no moderator yet there is no-one he can ask to get
	 * the moderation, in case its a Non-Moderated Room he should then get the
	 * Moderation without any confirmation needed
	 * 
	 * @return Long 1 => means get Moderation, 2 => ask Moderator for
	 *         Moderation, 3 => wait for Moderator
	 */
	public synchronized Long applyForModeration(String publicSID) {
		try {

			RoomClient currentClient = this.clientListManager
					.getClientByPublicSID(publicSID, false);

			List<RoomClient> currentModList = this.clientListManager
					.getCurrentModeratorByRoom(currentClient.getRoom_id());

			if (currentModList.size() > 0) {
				return 2L;
			} else {
				// No moderator in this room at the moment
				Rooms room = roommanagement.getRoomById(currentClient
						.getRoom_id());

				if (room.getIsModeratedRoom()) {
					return 3L;
				} else {
					return 1L;
				}
			}

		} catch (Exception err) {
			log.error("[applyForModeration]", err);
		}
		return -1L;
	}

	/**
	 * there will be set an attribute called "broadCastCounter" this is the name
	 * this user will publish his stream
	 * 
	 * @return long broadCastId
	 */
	public synchronized long getBroadCastId() {
		try {
			IConnection current = Red5.getConnectionLocal();
			String streamid = current.getClient().getId();
			RoomClient currentClient = this.clientListManager
					.getClientByStreamId(streamid);
			currentClient.setBroadCastID(broadCastCounter++);
			this.clientListManager.updateClientByStreamId(streamid,
					currentClient);
			return currentClient.getBroadCastID();
		} catch (Exception err) {
			log.error("[getBroadCastId]", err);
		}
		return -1;
	}

	/**
	 * this must be set _after_ the Video/Audio-Settings have been chosen (see
	 * editrecordstream.lzx) but _before_ anything else happens, it cannot be
	 * applied _after_ the stream has started! avsettings can be: av - video and
	 * audio a - audio only v - video only n - no a/v only static image
	 * furthermore
	 * 
	 * @param avsetting
	 * @param newMessage
	 * @return
	 */
	public synchronized RoomClient setUserAVSettings(String avsettings,
			Object newMessage, Integer vWidth, Integer vHeight, 
			long room_id, String publicSID, Integer interviewPodId) {
		try {

			IConnection current = Red5.getConnectionLocal();
			String streamid = current.getClient().getId();
			RoomClient currentClient = this.clientListManager
					.getClientByStreamId(streamid);
			currentClient.setAvsettings(avsettings);
			currentClient.setRoom_id(room_id);
			currentClient.setPublicSID(publicSID);
			currentClient.setIsAVClient(true);
			currentClient.setVWidth(vWidth);
			currentClient.setVHeight(vHeight);
			currentClient.setInterviewPodId(interviewPodId);
			// Long room_id = currentClient.getRoom_id();
			this.clientListManager.updateAVClientByStreamId(streamid,
					currentClient);

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

			Collection<Set<IConnection>> conCollection = current.getScope()
					.getConnections();
			for (Set<IConnection> conset : conCollection) {
				for (IConnection conn : conset) {
					if (conn != null) {
						if (conn instanceof IServiceCapableConnection) {
							RoomClient rcl = this.clientListManager
									.getClientByStreamId(conn.getClient()
											.getId());
							if (rcl == null) {
								// continue;
							} else if (rcl.getIsScreenClient() != null
									&& rcl.getIsScreenClient()) {
								// continue;
							} else {
								((IServiceCapableConnection) conn).invoke(
										"sendVarsToMessageWithClient",
										new Object[] { hsm }, this);
							}
						}
					}
				}
			}

			return currentClient;
		} catch (Exception err) {
			log.error("[setUserAVSettings]", err);
		}
		return null;
	}

	/*
	 * checks if the user is allowed to apply for Moderation
	 */
	public synchronized Boolean checkRoomValues(Long room_id) {
		try {

			// appointed meeting or moderated Room?
			Rooms room = roommanagement.getRoomById(room_id);

			// not really - default logic
			if (room.getAppointment() == null || room.getAppointment() == false) {

				if (room.getIsModeratedRoom()) {

					// if this is a Moderated Room then the Room can be only
					// locked off by the Moderator Bit
					List<RoomClient> clientModeratorListRoom = this.clientListManager
							.getCurrentModeratorByRoom(room_id);

					// If there is no Moderator yet and we are asking for it
					// then deny it
					// cause at this moment, the user should wait untill a
					// Moderator enters the Room
					if (clientModeratorListRoom.size() == 0) {
						return false;
					} else {
						return true;
					}

				} else {
					return true;
				}

			} else {

				// FIXME: TODO: For Rooms that are created as Appointment we
				// have to check that too
				// but I don't know yet the Logic behind it - swagner 19.06.2009
				return true;

			}

		} catch (Exception err) {
			log.error("[checkRoomValues]", err);
		}
		return false;
	}

	/**
	 * This function is called once a User enters a Room
	 * 
	 * It contains several different mechanism depending on what roomtype and
	 * what options are available for the room to find out if the current user
	 * will be a moderator of that room or not<br/>
	 * <br/>
	 * Some rules:<br/>
	 * <ul>
	 * <li>If it is a room that was created through the calendar, the user that
	 * organized the room will be moderator, the param Boolean becomeModerator
	 * will be ignored then</li>
	 * <li>In regular rooms you can use the param Boolean becomeModerator to set
	 * any user to become a moderator of the room</li>
	 * </ul>
	 * <br/>
	 * If a new moderator is detected a Push Call to all current users of the
	 * room is invoked "setNewModeratorByList" to notify them of the new
	 * moderator<br/>
	 * <br/>
	 * And the end of the mechanism a push call with the new client-object
	 * and all the informations about the new user is send to every user of the
	 * current conference room<br/>
	 * <br/>
	 * @param room_id
	 * @param colorObj
	 * @return
	 */
	public synchronized RoomStatus setRoomValues(Long room_id,
			Boolean becomeModerator, Boolean isSuperModerator,
			Long organization_id, String colorObj) {
		try {

			// Return Object
			RoomStatus roomStatus = new RoomStatus();

			IConnection current = Red5.getConnectionLocal();
			String streamid = current.getClient().getId();
			RoomClient currentClient = this.clientListManager
					.getClientByStreamId(streamid);
			currentClient.setRoom_id(room_id);
			currentClient.setIsAVClient(false);
			currentClient.setRoomEnter(new Date());
			currentClient.setOrganization_id(organization_id);

			currentClient.setUsercolor(colorObj);

			// Inject externalUserId if nothing is set yet
			if (currentClient.getExternalUserId() == null) {
				Users us = usersDao.getUser(currentClient.getUser_id());
				if (us != null) {
					currentClient.setExternalUserId(us.getExternalUserId());
					currentClient.setExternalUserType(us.getExternalUserType());
				}
			}

			// This can be set without checking for Moderation Flag
			currentClient.setIsSuperModerator(isSuperModerator);

			this.clientListManager.updateClientByStreamId(streamid,
					currentClient);

            Rooms room = roommanagement.getRoomById(room_id);
            if (room.getShowMicrophoneStatus()) {
            	currentClient.setCanGiveAudio(true);
            }

			// Log the User
			conferenceLogDao.addConferenceLog("roomEnter",
					currentClient.getUser_id(), streamid, room_id,
					currentClient.getUserip(), "",
					currentClient.getExternalUserId(),
					currentClient.getExternalUserType(),
					currentClient.getMail(), currentClient.getFirstname(),
					currentClient.getLastname());

			log.debug("##### setRoomValues : " + currentClient);
			
			// Check for Moderation LogicalRoom ENTER
			HashMap<String, RoomClient> clientListRoom = this.clientListManager
					.getRoomClients(room_id);

			// appointed meeting or moderated Room? => Check Max Users first
			if (room.getNumberOfPartizipants() != null
					&& clientListRoom.size() > room.getNumberOfPartizipants()) {
				roomStatus.setRoomFull(true);
				return roomStatus;
			}

			// default logic for non regular rooms
			if (room.getAppointment() == null || room.getAppointment() == false) {

				if (room.getIsModeratedRoom()) {

					// if this is a Moderated Room then the Room can be only
					// locked off by the Moderator Bit
					// List<RoomClient> clientModeratorListRoom =
					// this.clientListManager.getCurrentModeratorByRoom(room_id);

					// If there is no Moderator yet we have to check if the
					// current User has the Bit set to true to
					// become one, otherwise he won't get Moderation and has to
					// wait
					if (becomeModerator) {
						currentClient.setIsMod(true);

						// There is a need to send an extra Event here, cause at
						// this moment there could be
						// already somebody in the Room waiting

						// Update the Client List
						this.clientListManager.updateClientByStreamId(streamid,
								currentClient);

						List<RoomClient> modRoomList = this.clientListManager
								.getCurrentModeratorByRoom(currentClient.getRoom_id());
						
						//Sync message to everybody
						syncMessageToCurrentScope("setNewModeratorByList", modRoomList, false);

					} else {
						// The current User is not a Teacher/Admin or whatever
						// Role that should get the
						// Moderation
						currentClient.setIsMod(false);
					}

				} else {

					// If this is a normal Room Moderator rules : first come,
					// first draw ;-)
					log.debug("setRoomValues : Room"
							+ room_id
							+ " not appointed! Moderator rules : first come, first draw ;-)");
					if (clientListRoom.size() == 1) {
						log.debug("Room is empty so set this user to be moderation role");
						currentClient.setIsMod(true);
					} else {
						log.debug("Room is already somebody so set this user not to be moderation role");

						if (becomeModerator) {
							currentClient.setIsMod(true);

							// Update the Client List
							this.clientListManager.updateClientByStreamId(
									streamid, currentClient);

							List<RoomClient> modRoomList = this.clientListManager
									.getCurrentModeratorByRoom(currentClient
											.getRoom_id());

							// There is a need to send an extra Event here,
							// cause at this moment there could be
							// already somebody in the Room waiting -swagner check this comment, 20.01.2012
							
							//Sync message to everybody
							syncMessageToCurrentScope("setNewModeratorByList", modRoomList, false);

						} else {
							// The current User is not a Teacher/Admin or
							// whatever Role that should get the Moderation
							currentClient.setIsMod(false);
						}

					}

				}

				// Update the Client List
				this.clientListManager.updateClientByStreamId(streamid,
						currentClient);

			} else {

				// If this is an Appointment then the Moderator will be set to
				// the Invitor

				Appointment ment = appointmentLogic
						.getAppointmentByRoom(room_id);

				List<MeetingMember> members = meetingMemberDao
						.getMeetingMemberByAppointmentId(ment
								.getAppointmentId());

				Long userIdInRoomClient = currentClient.getUser_id();

				boolean found = false;
				boolean moderator_set = false;

				// Check if current user is set to moderator
				for (int i = 0; i < members.size(); i++) {
					MeetingMember member = members.get(i);

					// only persistent users can schedule a meeting
					// user-id is only set for registered users
					if (member.getUserid() != null) {
						log.debug("checking user " + member.getFirstname()
								+ " for moderator role - ID : "
								+ member.getUserid().getUser_id());

						if (member.getUserid().getUser_id()
								.equals(userIdInRoomClient)) {
							found = true;

							if (member.getInvitor()) {
								log.debug("User "
										+ userIdInRoomClient
										+ " is moderator due to flag in MeetingMember record");
								currentClient.setIsMod(true);

								// Update the Client List
								this.clientListManager.updateClientByStreamId(
										streamid, currentClient);

								List<RoomClient> modRoomList = this.clientListManager
										.getCurrentModeratorByRoom(currentClient
												.getRoom_id());

								// There is a need to send an extra Event here, cause at this moment 
								// there could be already somebody in the Room waiting

								//Sync message to everybody
								syncMessageToCurrentScope("setNewModeratorByList", modRoomList, false);

								moderator_set = true;
								this.clientListManager.updateClientByStreamId(
										streamid, currentClient);
								break;
							} else {
								log.debug("User "
										+ userIdInRoomClient
										+ " is NOT moderator due to flag in MeetingMember record");
								currentClient.setIsMod(false);
								this.clientListManager.updateClientByStreamId(
										streamid, currentClient);
								break;
							}
						} else {
							if (member.getInvitor())
								moderator_set = true;
						}
					} else {
						if (member.getInvitor())
							moderator_set = true;
					}

				}

				if (!found) {
					log.debug("User "
							+ userIdInRoomClient
							+ " could not be found as MeetingMember -> definitely no moderator");
					currentClient.setIsMod(false);
					this.clientListManager.updateClientByStreamId(streamid,
							currentClient);
				} else {
					// if current user is part of the member list, but moderator
					// couldn't be retrieved : first come, first draw!
					if (clientListRoom.size() == 1 && moderator_set == false) {
						log.debug("");
						currentClient.setIsMod(true);

						// Update the Client List
						this.clientListManager.updateClientByStreamId(streamid,
								currentClient);

						List<RoomClient> modRoomList = this.clientListManager
								.getCurrentModeratorByRoom(currentClient
										.getRoom_id());

						// There is a need to send an extra Event here, cause at
						// this moment there could be
						// already somebody in the Room waiting

						//Sync message to everybody
						syncMessageToCurrentScope("setNewModeratorByList", modRoomList, false);
						
						this.clientListManager.updateClientByStreamId(streamid,
								currentClient);
					}
				}

			}
			
			
			//Sync message to everybody
			syncMessageToCurrentScope("addNewUser", currentClient, false);

			//Status object for Shared Browsing
			BrowserStatus browserStatus = (BrowserStatus) current.getScope()
					.getAttribute("browserStatus");

			if (browserStatus == null) {
				browserStatus = new BrowserStatus();
			}

			// RoomStatus roomStatus = new RoomStatus();

			// FIXME: Rework Client Object to DTOs
			roomStatus.setClientMap(clientListRoom);
			roomStatus.setBrowserStatus(browserStatus);

			return roomStatus;
		} catch (Exception err) {
			log.error("[setRoomValues]", err);
		}
		return null;
	}

	/**
	 * This method is invoked when the user has disconnected and reconnects to
	 * the Gateway with the new scope
	 * 
	 * @param SID
	 * @param userId
	 * @param username
	 * @param firstname
	 * @param lastname
	 * @param picture_uri
	 * @return
	 */
	public synchronized RoomClient setUsernameReconnect(String SID,
			Long userId, String username, String firstname, String lastname,
			String picture_uri) {
		try {
			IConnection current = Red5.getConnectionLocal();
			String streamid = current.getClient().getId();
			RoomClient currentClient = this.clientListManager
					.getClientByStreamId(streamid);

			currentClient.setUsername(username);
			currentClient.setUser_id(userId);
			currentClient.setPicture_uri(picture_uri);
			currentClient.setUserObject(userId, username, firstname, lastname);

			// Update Session Data
			sessionManagement.updateUserWithoutSession(SID, userId);

			Users user = userManagement.getUserById(userId);

			if (user != null) {
				currentClient.setExternalUserId(user.getExternalUserId());
				currentClient.setExternalUserType(user.getExternalUserType());
			}

			// only fill this value from User-Record
			// cause invited users have non
			// you cannot set the firstname,lastname from the UserRecord
			Users us = usersDao.getUser(userId);
			if (us != null && us.getPictureuri() != null) {
				// set Picture-URI
				currentClient.setPicture_uri(us.getPictureuri());
			}
			this.clientListManager.updateClientByStreamId(streamid,
					currentClient);
			return currentClient;
		} catch (Exception err) {
			log.error("[setUsername]", err);
		}
		return null;
	}

	/**
	 * this is set initial directly after login/loading language
	 * 
	 * @param userId
	 * @param username
	 * @param firstname
	 * @param lastname
	 * @param orgdomain
	 * @return
	 */
	public synchronized RoomClient setUsernameAndSession(String SID,
			Long userId, String username, String firstname, String lastname) {
		try {
			IConnection current = Red5.getConnectionLocal();
			String streamid = current.getClient().getId();
			RoomClient currentClient = this.clientListManager
					.getClientByStreamId(streamid);

			currentClient.setUsername(username);
			currentClient.setUser_id(userId);
			currentClient.setUserObject(userId, username, firstname, lastname);

			// Update Session Data
			log.debug("UDPATE SESSION " + SID + ", " + userId);
			sessionManagement.updateUserWithoutSession(SID, userId);

			Users user = userManagement.getUserById(userId);

			if (user != null) {
				currentClient.setExternalUserId(user.getExternalUserId());
				currentClient.setExternalUserType(user.getExternalUserType());
			}

			// only fill this value from User-Record
			// cause invited users have non
			// you cannot set the firstname,lastname from the UserRecord
			Users us = usersDao.getUser(userId);
			if (us != null && us.getPictureuri() != null) {
				// set Picture-URI
				currentClient.setPicture_uri(us.getPictureuri());
			}
			this.clientListManager.updateClientByStreamId(streamid,
					currentClient);
			return currentClient;
		} catch (Exception err) {
			log.error("[setUsername]", err);
		}
		return null;
	}

	/**
	 * used by the Screen-Sharing Servlet to trigger events
	 * 
	 * @param room_id
	 * @param message
	 * @return
	 */
	public synchronized HashMap<String, RoomClient> sendMessageByRoomAndDomain(
			Long room_id, Object message) {
		HashMap<String, RoomClient> roomClientList = new HashMap<String, RoomClient>();
		try {

			log.debug("sendMessageByRoomAndDomain " + room_id);

			IScope globalScope = getContext().getGlobalScope();

			IScope webAppKeyScope = globalScope
					.getScope(OpenmeetingsVariables.webAppRootKey);

			log.debug("webAppKeyScope " + webAppKeyScope);

			IScope scopeHibernate = webAppKeyScope.getScope(room_id.toString());
			// IScope scopeHibernate = webAppKeyScope.getScope("hibernate");

			if (scopeHibernate != null) {

				Collection<Set<IConnection>> conCollection = webAppKeyScope
						.getScope(room_id.toString()).getConnections();
				for (Set<IConnection> conset : conCollection) {
					for (IConnection conn : conset) {
						if (conn != null) {
							RoomClient rcl = this.clientListManager
									.getClientByStreamId(conn.getClient()
											.getId());
							if (rcl == null) {
								// continue;
							} else if (rcl.getIsScreenClient() != null
									&& rcl.getIsScreenClient()) {
								// continue;
							} else {
								if (conn instanceof IServiceCapableConnection) {
									// RoomClient rcl =
									// this.clientListManager.getClientByStreamId(conn.getClient().getId());
									((IServiceCapableConnection) conn).invoke(
											"newMessageByRoomAndDomain",
											new Object[] { message }, this);

									// log.debug("sending newMessageByRoomAndDomain to "
									// + conn);
								}
							}
						}
					}
				}

			} else {
				log.debug("sendMessageByRoomAndDomain servlet not yet started  - roomID : '"
						+ room_id + "'");
			}

		} catch (Exception err) {
			log.error("[getClientListBYRoomAndDomain]", err);
		}
		return roomClientList;
	}

	public synchronized List<RoomClient> getCurrentModeratorList() {
		try {
			log.debug("*..*getCurrentModerator id: ");

			IConnection current = Red5.getConnectionLocal();
			RoomClient currentClient = this.clientListManager
					.getClientByStreamId(current.getClient().getId());
			Long room_id = currentClient.getRoom_id();

			// log.debug("Who is this moderator? "+currentMod);

			return this.clientListManager.getCurrentModeratorByRoom(room_id);
		} catch (Exception err) {
			log.error("[getCurrentModerator]", err);
		}
		return null;
	}

	/**
	 * This Function is triggered from the Whiteboard
	 * 
	 * @param whiteboardObj
	 * @return
	 */
	@SuppressWarnings({ "rawtypes", "unchecked" })
	public synchronized void sendVars(ArrayList whiteboardObjParam) {
		//
		try {

			// In previous version this has been always a Map, now its a List
			// so I re-wrapp that class to be a Map again.
			// swagner 13.02.2009
			// log.debug("*..*sendVars1: " + whiteboardObjParam);
			// log.debug("*..*sendVars2: " + whiteboardObjParam.getClass());
			// log.debug("*..*sendVars3: " +
			// whiteboardObjParam.getClass().getName());

			Map whiteboardObj = new HashMap();
			int i = 0;
			for (Iterator iter = whiteboardObjParam.iterator(); iter.hasNext();) {
				Object obj = iter.next();
				// log.debug("obj"+obj);
				whiteboardObj.put(i, obj);
				i++;
			}

			// Map whiteboardObj = (Map) whiteboardObjParam;

			// Check if this User is the Mod:
			IConnection current = Red5.getConnectionLocal();
			RoomClient currentClient = this.clientListManager
					.getClientByStreamId(current.getClient().getId());

			if (currentClient == null) {
				return;
			}

			Long room_id = currentClient.getRoom_id();

			String action = whiteboardObj.get(2).toString();

			// log.debug("***** sendVars: " + actionObject.get(0));

			if (action != null && action.equals("whiteboardObj")) {
				// Update Whiteboard Object
				List actionObject = (List) whiteboardObj.get(3);
				WhiteboardManagement.getInstance().updateWhiteboardObject(
						room_id, actionObject);
			} else if (action != null && action.equals("moveMap")) {
				// Update Whiteboard Object
				List actionObject = (List) whiteboardObj.get(3);
				WhiteboardManagement.getInstance().updateWhiteboardObjectPos(
						room_id, actionObject);
			} else {
				// Store event in list
				WhiteboardManagement.getInstance().addWhiteBoardObject(room_id,
						whiteboardObj);
			}

			boolean showDrawStatus = getWhiteboardDrawStatus();

			// Notify all Clients of that Scope (Room)
			Collection<Set<IConnection>> conCollection = current.getScope()
					.getConnections();
			for (Set<IConnection> conset : conCollection) {
				for (IConnection conn : conset) {
					if (conn != null) {
						if (conn instanceof IServiceCapableConnection) {

							if (conn.getClient().getId()
									.equals(current.getClient().getId())) {
								continue;
							}

							RoomClient rcl = this.clientListManager
									.getSyncClientByStreamId(conn.getClient()
											.getId());

							if (rcl == null) {
								continue;
							}

							if (!currentClient.getStreamid().equals(
									rcl.getStreamid())) {
								((IServiceCapableConnection) conn)
										.invoke("sendVarsToWhiteboard",
												new Object[] {
														(showDrawStatus ? currentClient
																: null),
														whiteboardObj }, this);
							}
						}
					}
				}
			}

		} catch (Exception err) {
			log.error("[sendVars]", err);
		}
	}

	/**
	 * This Function is triggered from the Whiteboard
	 * 
	 * @param whiteboardObj
	 * @return
	 */
	@SuppressWarnings({ "rawtypes", "unchecked" })
	public synchronized void sendVarsByWhiteboardId(
			ArrayList whiteboardObjParam, Long whiteboardId) {
		//
		try {

			Map whiteboardObj = new HashMap();
			int i = 0;
			for (Iterator iter = whiteboardObjParam.iterator(); iter.hasNext();) {
				Object obj = iter.next();
				// log.debug("obj"+obj);
				whiteboardObj.put(i, obj);
				i++;
			}

			// Check if this User is the Mod:
			IConnection current = Red5.getConnectionLocal();
			RoomClient currentClient = this.clientListManager
					.getClientByStreamId(current.getClient().getId());

			if (currentClient == null) {
				return;
			}

			Long room_id = currentClient.getRoom_id();

			// log.debug("***** sendVars: " + whiteboardObj);

			// Store event in list
			String action = whiteboardObj.get(2).toString();

			if (action.equals("deleteMindMapNodes")) {

				// Simulate Single Delete Events for z-Index
				List actionObject = (List) whiteboardObj.get(3);

				List<List> itemObjects = (List) actionObject.get(3);

				Map whiteboardTempObj = new HashMap();
				whiteboardTempObj.put(2, "delete");

				for (List itemObject : itemObjects) {

					List<Object> tempActionObject = new LinkedList<Object>();
					tempActionObject.add("mindmapnode");
					tempActionObject.add(itemObject.get(0)); // z-Index -8
					tempActionObject.add(null); // simulate -7
					tempActionObject.add(null); // simulate -6
					tempActionObject.add(null); // simulate -5
					tempActionObject.add(null); // simulate -4
					tempActionObject.add(null); // simulate -3
					tempActionObject.add(null); // simulate -2
					tempActionObject.add(itemObject.get(1)); // Object-Name -1

					whiteboardTempObj.put(3, tempActionObject);

					WhiteboardManagement.getInstance().addWhiteBoardObjectById(
							room_id, whiteboardTempObj, whiteboardId);

				}

			} else {

				WhiteboardManagement.getInstance().addWhiteBoardObjectById(
						room_id, whiteboardObj, whiteboardId);

			}

			// This is no longer necessary
			// boolean ismod = currentClient.getIsMod();

			// log.debug("*..*ismod: " + ismod);

			// if (ismod) {

			Map<String, Object> sendObject = new HashMap<String, Object>();
			sendObject.put("id", whiteboardId);
			sendObject.put("param", whiteboardObjParam);

			boolean showDrawStatus = getWhiteboardDrawStatus();

			// Notify all Clients of that Scope (Room)
			Collection<Set<IConnection>> conCollection = current.getScope()
					.getConnections();
			for (Set<IConnection> conset : conCollection) {
				for (IConnection conn : conset) {
					if (conn != null) {
						if (conn instanceof IServiceCapableConnection) {
							if (conn.getClient().getId()
									.equals(current.getClient().getId())) {
								continue;
							}

							RoomClient rcl = this.clientListManager
									.getSyncClientByStreamId(conn.getClient()
											.getId());

							if (rcl == null) {
								continue;
							}

							if (!currentClient.getStreamid().equals(
									rcl.getStreamid())) {
								((IServiceCapableConnection) conn).invoke(
										"sendVarsToWhiteboardById",
										new Object[] {
												showDrawStatus ? currentClient
														: null, sendObject },
										this);
							}
						}
					}
				}
			}

			// return numberOfUsers;
			// } else {
			// // log.debug("*..*you are not allowed to send: "+ismod);
			// return -1;
			// }
		} catch (Exception err) {
			log.error("[sendVarsByWhiteboardId]", err);
		}
	}

	public synchronized int sendVarsModeratorGeneral(Object vars) {
		log.debug("*..*sendVars: " + vars);
		try {
			IConnection current = Red5.getConnectionLocal();
			RoomClient currentClient = this.clientListManager
					.getClientByStreamId(current.getClient().getId());
			// Long room_id = currentClient.getRoom_id();

			log.debug("***** id: " + currentClient.getStreamid());

			boolean ismod = currentClient.getIsMod();

			if (ismod) {
				log.debug("CurrentScope :" + current.getScope().getName());
				// Send to all Clients of the same Scope
				Collection<Set<IConnection>> conCollection = current.getScope()
						.getConnections();
				for (Set<IConnection> conset : conCollection) {
					for (IConnection conn : conset) {
						if (conn != null) {
							if (conn instanceof IServiceCapableConnection) {
								RoomClient rcl = this.clientListManager
										.getClientByStreamId(conn.getClient()
												.getId());
								if (rcl == null) {
									// continue;
								} else if (rcl.getIsScreenClient() != null
										&& rcl.getIsScreenClient()) {
									// continue;
								} else {
									// log.debug("*..*idremote: " +
									// rcl.getStreamid());
									// log.debug("*..*my idstreamid: " +
									// currentClient.getStreamid());
									if (!currentClient.getStreamid().equals(
											rcl.getStreamid())) {
										((IServiceCapableConnection) conn)
												.invoke("sendVarsToModeratorGeneral",
														new Object[] { vars },
														this);
										// log.debug("sending sendVarsToModeratorGeneral to "
										// + conn);
									}
								}
							}
						}
					}
				}
				return 1;
			} else {
				// log.debug("*..*you are not allowed to send: "+ismod);
				return -1;
			}
		} catch (Exception err) {
			log.error("[sendVarsModeratorGeneral]", err);
		}
		return -1;
	}

	public synchronized int sendMessage(Object newMessage) {
		try {
			
			syncMessageToCurrentScope("sendVarsToMessage", newMessage, false);
			
		} catch (Exception err) {
			log.error("[sendMessage]", err);
		}
		return 1;
	}
	
	public synchronized int sendMessageAll(Object newMessage) {
		try {
			
			syncMessageToCurrentScope("sendVarsToMessage", newMessage, true);
			
		} catch (Exception err) {
			log.error("[sendMessage]", err);
		}
		return 1;
	}

	/**
	 * send status for shared browsing to all members except self
	 * @param newMessage
	 * @return
	 */
	@SuppressWarnings({ "rawtypes" })
	public synchronized int sendBrowserMessageToMembers(Object newMessage) {
		try {
			IConnection current = Red5.getConnectionLocal();

			List newMessageList = (List) newMessage;

			String action = newMessageList.get(0).toString();

			BrowserStatus browserStatus = (BrowserStatus) current.getScope()
					.getAttribute("browserStatus");

			if (browserStatus == null) {
				browserStatus = new BrowserStatus();
			}

			if (action.equals("initBrowser") || action.equals("newBrowserURL")) {
				browserStatus.setBrowserInited(true);
				browserStatus.setCurrentURL(newMessageList.get(1).toString());
			} else if (action.equals("closeBrowserURL")) {
				browserStatus.setBrowserInited(false);
			}

			current.getScope().setAttribute("browserStatus", browserStatus);
			
			syncMessageToCurrentScope("sendVarsToMessage", newMessage, false);

		} catch (Exception err) {
			log.error("[sendMessage]", err);
		}
		return 1;
	}

	/**
	 * wrapper method
	 * @param newMessage
	 * @return
	 */
	public synchronized int sendMessageToMembers(Object newMessage) {
		try {
			
			//Sync to all users of current scope
			syncMessageToCurrentScope("sendVarsToMessage", newMessage, false);
			
		} catch (Exception err) {
			log.error("[sendMessage]", err);
		}
		return 1;
	}
	
	/**
	 * General sync mechanism for all messages that are send from within the 
	 * scope of the current client, but:
	 * <ul>
	 * <li>optionally do not send to self (see param: sendSelf)</li>
	 * <li>do not send to clients that are screen sharing clients</li>
	 * <li>do not send to clients that are audio/video clients (or potentially ones)</li>
	 * <li>do not send to connections where no RoomClient is registered</li>
	 * </ul>
	 *  
	 * @param remoteMethodName
	 * @param newMessage
	 * @param sendSelf 
	 * @return
	 */
	public synchronized int syncMessageToCurrentScope(String remoteMethodName, Object newMessage, boolean sendSelf) {
		try {
			IConnection current = Red5.getConnectionLocal();

			// Send to all Clients of that Scope(Room)
			Collection<Set<IConnection>> conCollection = current.getScope()
					.getConnections();
			for (Set<IConnection> conset : conCollection) {
				for (IConnection conn : conset) {
					if (conn != null) {
						if (conn instanceof IServiceCapableConnection) {
							RoomClient rcl = this.clientListManager
									.getClientByStreamId(conn.getClient().getId());
							
							if (rcl == null) {
								// RoomClient can be null if there are network problems
								continue;
							} else if (rcl.getIsScreenClient() != null && rcl
											.getIsScreenClient()) {
								// screen sharing clients do not receive events
								continue;
							} else if (rcl.getIsAVClient()) {
								// AVClients or potential AVClients do not receive events
								continue;
							} else if (current.getClient().getId().equals(
										conn.getClient().getId()) && !sendSelf) {
								//Do not send back to self
								continue;
							}
							
							((IServiceCapableConnection) conn).invoke(
									remoteMethodName, new Object[] { newMessage }, this);
							
						}
					}
				}
			}
		} catch (Exception err) {
			log.error("[syncMessageToCurrentScope]", err);
		}
		return 1;
	}

	/**
	 * wrapper method
	 * @param newMessage
	 * @return
	 */
	public synchronized int sendMessageWithClient(Object newMessage) {
		try {
			sendMessageWithClientWithSyncObject(newMessage, true);

		} catch (Exception err) {
			log.error("[sendMessageWithClient] ", err);
			return -1;
		}
		return 1;
	}
	
	/**
	 * wrapper method
	 * @param newMessage
	 * @param sync
	 * @return
	 */
	public synchronized int sendMessageWithClientWithSyncObject(Object newMessage, boolean sync) {
		try {
			IConnection current = Red5.getConnectionLocal();
			RoomClient currentClient = this.clientListManager
					.getClientByStreamId(current.getClient().getId());

			HashMap<String, Object> hsm = new HashMap<String, Object>();
			hsm.put("client", currentClient);
			hsm.put("message", newMessage);
			
			//Sync to all users of current scope
			syncMessageToCurrentScope("sendVarsToMessageWithClient", hsm, sync);

		} catch (Exception err) {
			log.error("[sendMessageWithClient] ", err);
			return -1;
		}
		return 1;
	}

	/**
	 * Function is used to send the kick Trigger at the moment, 
	 * it sends a general message to a specific clientId
	 * 
	 * @param newMessage
	 * @param clientId
	 * @return
	 */
	public synchronized int sendMessageById(Object newMessage, String clientId,
			IScope scope) {
		try {
			log.debug("### sendMessageById ###" + clientId);

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

			// broadcast Message to specific user with id inside the same Scope
			Collection<Set<IConnection>> conCollection = scope.getConnections();

			for (Set<IConnection> conset : conCollection) {
				for (IConnection conn : conset) {
					if (conn != null) {
						if (conn instanceof IServiceCapableConnection) {
							RoomClient rcl = this.clientListManager
									.getClientByStreamId(conn.getClient()
											.getId());
							if (rcl == null) {
								// continue;
							} else if (rcl.getIsScreenClient() != null
									&& rcl.getIsScreenClient()) {
								// continue;
							} else {
								// log.debug("### sendMessageById 1 ###"+clientId);
								// log.debug("### sendMessageById 2 ###"+conn.getClient().getId());
								if (conn.getClient().getId().equals(clientId)) {
									((IServiceCapableConnection) conn).invoke(
											"sendVarsToMessageWithClient",
											new Object[] { hsm }, this);
									// log.debug("sendingsendVarsToMessageWithClient ByID to "
									// + conn);
								}
							}
						}
					}
				}
			}
		} catch (Exception err) {
			log.error("[sendMessageWithClient] ", err);
			return -1;
		}
		return 1;
	}

	/**
	 * Sends a message to a user in the same room by its clientId
	 * 
	 * @param newMessage
	 * @param clientId
	 * @return
	 */
	public synchronized int sendMessageWithClientById(Object newMessage,
			String clientId) {
		try {
			IConnection current = Red5.getConnectionLocal();
			RoomClient currentClient = this.clientListManager
					.getClientByStreamId(current.getClient().getId());

			log.debug("### sendMessageWithClientById ###" + clientId);

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

			// broadcast Message to specific user with id inside the same Scope
			Collection<Set<IConnection>> conCollection = current.getScope()
					.getConnections();
			for (Set<IConnection> conset : conCollection) {
				for (IConnection conn : conset) {
					if (conn != null) {
						RoomClient rcl = this.clientListManager
								.getClientByStreamId(conn.getClient().getId());
						if (rcl == null) {
							// continue;
						} else if (rcl.getIsScreenClient() != null
								&& rcl.getIsScreenClient()) {
							// continue;
						} else {
							if (conn instanceof IServiceCapableConnection) {
								// log.debug("### sendMessageWithClientById 1 ###"+clientId);
								// log.debug("### sendMessageWithClientById 2 ###"+conn.getClient().getId());
								if (conn.getClient().getId().equals(clientId)) {
									((IServiceCapableConnection) conn).invoke(
											"sendVarsToMessageWithClient",
											new Object[] { hsm }, this);
									// log.debug("sendingsendVarsToMessageWithClient ByID to "
									// + conn);
								}
							}
						}
					}
				}
			}
		} catch (Exception err) {
			log.error("[sendMessageWithClient] ", err);
			return -1;
		}
		return 1;
	}

	public synchronized void sendMessageWithClientByPublicSID(Object message,
			String publicSID) {
		try {
			// ApplicationContext appCtx = getContext().getApplicationContext();
			IScope globalScope = getContext().getGlobalScope();

			IScope webAppKeyScope = globalScope
					.getScope(OpenmeetingsVariables.webAppRootKey);

			// log.debug("webAppKeyScope "+webAppKeyScope);

			// Get Room Id to send it to the correct Scope
			RoomClient currentClient = this.clientListManager
					.getClientByPublicSID(publicSID, false);

			if (currentClient == null) {
				throw new Exception(
						"Could not Find RoomClient on List publicSID: "
								+ publicSID);
			}
			// default Scope Name
			String scopeName = "hibernate";
			if (currentClient.getRoom_id() != null) {
				scopeName = currentClient.getRoom_id().toString();
			}

			IScope scopeHibernate = webAppKeyScope.getScope(scopeName);

			// log.debug("scopeHibernate "+scopeHibernate);

			if (scopeHibernate != null) {
				// Notify the clients of the same scope (room) with user_id

				Collection<Set<IConnection>> conCollection = webAppKeyScope
						.getScope(scopeName).getConnections();
				for (Set<IConnection> conset : conCollection) {
					for (IConnection conn : conset) {
						if (conn != null) {
							RoomClient rcl = this.clientListManager
									.getClientByStreamId(conn.getClient()
											.getId());
							if (rcl != null) {
								if (rcl.getIsScreenClient() != null
										&& rcl.getIsScreenClient()) {
									// continue;
								} else {
									// log.debug("rcl "+rcl+" rcl.getUser_id(): "+rcl.getPublicSID()+" publicSID: "+publicSID+
									// " IS EQUAL? "+rcl.getPublicSID().equals(publicSID));
									if (rcl.getPublicSID().equals(publicSID)) {
										// log.debug("IS EQUAL ");
										((IServiceCapableConnection) conn)
												.invoke("newMessageByRoomAndDomain",
														new Object[] { message },
														this);
										log.debug("newMessageByRoomAndDomain RPC:newMessageByRoomAndDomain"
												+ message);
									}
								}
							}
						}
					}
				}

			} else {
				// Scope not yet started
			}
		} catch (Exception err) {
			log.error("[sendMessageWithClient] ", err);
			err.printStackTrace();
		}
	}

	public synchronized void sendMessageWithClientByPublicSIDOrUser(
			Object message, String publicSID, Long user_id) {
		try {
			// ApplicationContext appCtx = getContext().getApplicationContext();

			IScope globalScope = getContext().getGlobalScope();

			IScope webAppKeyScope = globalScope
					.getScope(OpenmeetingsVariables.webAppRootKey);

			// log.debug("webAppKeyScope "+webAppKeyScope);

			// Get Room Id to send it to the correct Scope
			RoomClient currentClient = this.clientListManager
					.getClientByPublicSID(publicSID, false);

			if (currentClient == null) {
				currentClient = this.clientListManager
						.getClientByUserId(user_id);
			}

			Collection<Set<IConnection>> conCollection = null;

			if (currentClient == null) {
				// Must be from a previous session, search for user in current
				// scope
				IConnection current = Red5.getConnectionLocal();
				// Notify all Clients of that Scope (Room)
				conCollection = current.getScope().getConnections();
			} else {
				// default Scope Name
				String scopeName = "hibernate";
				if (currentClient.getRoom_id() != null) {
					scopeName = currentClient.getRoom_id().toString();
				}

				IScope scopeHibernate = webAppKeyScope.getScope(scopeName);

				if (scopeHibernate != null) {
					conCollection = webAppKeyScope.getScope(scopeName)
							.getConnections();
				}
			}

			// log.debug("scopeHibernate "+scopeHibernate);

			// Notify the clients of the same scope (room) with user_id

			for (Set<IConnection> conset : conCollection) {
				for (IConnection conn : conset) {
					if (conn != null) {
						RoomClient rcl = this.clientListManager
								.getClientByStreamId(conn.getClient().getId());
						if (rcl != null) {
							if (rcl.getIsScreenClient() != null
									&& rcl.getIsScreenClient()) {
								// continue;
							} else {
								// log.debug("rcl "+rcl+" rcl.getUser_id(): "+rcl.getPublicSID()+" publicSID: "+publicSID+
								// " IS EQUAL? "+rcl.getPublicSID().equals(publicSID));
								if (rcl.getPublicSID().equals(publicSID)) {
									// log.debug("IS EQUAL ");
									((IServiceCapableConnection) conn).invoke(
											"newMessageByRoomAndDomain",
											new Object[] { message }, this);
									log.debug("sendMessageWithClientByPublicSID RPC:newMessageByRoomAndDomain"
											+ message);
								} else if (user_id != 0
										&& rcl.getUser_id() != null
										&& rcl.getUser_id().equals(user_id)) {
									((IServiceCapableConnection) conn).invoke(
											"newMessageByRoomAndDomain",
											new Object[] { message }, this);
									log.debug("sendMessageWithClientByPublicSID RPC:newMessageByRoomAndDomain"
											+ message);
								}
							}
						}
					}
				}
			}

		} catch (Exception err) {
			log.error("[sendMessageWithClient] ", err);
			err.printStackTrace();
		}
	}

	public synchronized Boolean getInterviewRecordingStatus() {
		try {

			IConnection current = Red5.getConnectionLocal();

			Collection<Set<IConnection>> conCollection = current.getScope()
					.getConnections();
			for (Set<IConnection> conset : conCollection) {
				for (IConnection conn : conset) {
					if (conn != null) {

						RoomClient rcl = this.clientListManager
								.getClientByStreamId(conn.getClient().getId());

						if (rcl.getIsRecording() != null
								&& rcl.getIsRecording()) {
							return true;
						}

					}
				}
			}

			return false;
		} catch (Exception err) {
			log.error("[getInterviewRecordingStatus]", err);
		}

		return null;
	}

	public synchronized Boolean startInterviewRecording() {
		try {

			IConnection current = Red5.getConnectionLocal();

			Collection<Set<IConnection>> conCollection = current.getScope()
					.getConnections();
			for (Set<IConnection> conset : conCollection) {
				for (IConnection conn : conset) {
					if (conn != null) {

						RoomClient rcl = this.clientListManager
								.getClientByStreamId(conn.getClient().getId());

						if (rcl.getIsRecording() != null
								&& rcl.getIsRecording()) {
							return false;
						}

					}
				}
			}

			RoomClient current_rcl = this.clientListManager
					.getClientByStreamId(current.getClient().getId());

			// Also set the Recording Flag to Record all Participants that enter
			// later
			current_rcl.setIsRecording(true);
			this.clientListManager.updateClientByStreamId(current.getClient()
					.getId(), current_rcl);

			Map<String, String> interviewStatus = new HashMap<String, String>();
			interviewStatus.put("action", "start");

			for (Set<IConnection> conset : conCollection) {
				for (IConnection conn : conset) {
					if (conn != null) {
						
						RoomClient rcl = this.clientListManager
								.getClientByStreamId(conn.getClient().getId());
						
						if (rcl == null) {
							continue;
						} else if (rcl.getIsAVClient()) {
							continue;
						} else if (rcl.getIsScreenClient() != null && rcl.getIsScreenClient()) {
							continue;
						}

						((IServiceCapableConnection) conn).invoke(
								"interviewStatus",
								new Object[] { interviewStatus }, this);
						log.debug("-- interviewStatus" + interviewStatus);

					}
				}
			}

			String recordingName = "Interview "
					+ CalendarPatterns.getDateWithTimeByMiliSeconds(new Date());

			this.flvRecorderService
					.recordMeetingStream(recordingName, "", true);

			return true;

		} catch (Exception err) {
			log.debug("[startInterviewRecording]", err);
		}
		return null;
	}

	@SuppressWarnings({ "rawtypes" })
	public synchronized Boolean sendRemoteCursorEvent(String streamid,
			Map messageObj) {
		try {

			IConnection current = Red5.getConnectionLocal();

			Collection<Set<IConnection>> conCollection = current.getScope()
					.getConnections();
			for (Set<IConnection> conset : conCollection) {
				for (IConnection conn : conset) {
					if (conn != null) {

						RoomClient rcl = this.clientListManager
								.getClientByStreamId(conn.getClient().getId());

						if (rcl == null) {
							// continue;
						} else if (rcl.getIsScreenClient() != null
								&& rcl.getIsScreenClient()) {

							if (rcl.getStreamid() != null
									&& rcl.getStreamid().equals(streamid)) {
								((IServiceCapableConnection) conn).invoke(
										"sendRemoteCursorEvent",
										new Object[] { messageObj }, this);
								log.debug("sendRemoteCursorEvent messageObj"
										+ messageObj);
							}

						}

					}
				}
			}
		} catch (Exception err) {
			log.debug("[sendRemoteCursorEvent]", err);
		}
		return null;
	}
	
	//FIXME: legacy code, needs to be removed
	public boolean checkSharerSession() {
		return true;
	}

	/**
	 * Stop the recording of the streams and send event to connected users of scope
	 * 
	 * @return
	 */
	public synchronized Boolean stopInterviewRecording() {
		try {

			IConnection current = Red5.getConnectionLocal();

			boolean found = false;
			Long flvRecordingId = null;

			Collection<Set<IConnection>> conCollection = current.getScope()
					.getConnections();
			for (Set<IConnection> conset : conCollection) {
				for (IConnection conn : conset) {
					if (conn != null) {

						RoomClient rcl = this.clientListManager
								.getClientByStreamId(conn.getClient().getId());

						if (rcl.getIsRecording() != null
								&& rcl.getIsRecording()) {

							rcl.setIsRecording(false);

							flvRecordingId = rcl.getFlvRecordingId();

							rcl.setFlvRecordingId(null);

							// Reset the Recording Flag to Record all
							// Participants that enter later
							this.clientListManager.updateClientByStreamId(conn
									.getClient().getId(), rcl);

							found = true;
						}

					}
				}
			}

			if (!found) {
				return false;
			}

			RoomClient currentClient = this.clientListManager
					.getClientByStreamId(current.getClient().getId());

			this.flvRecorderService.stopRecordAndSave(scope, currentClient,
					flvRecordingId);

			Map<String, String> interviewStatus = new HashMap<String, String>();
			interviewStatus.put("action", "stop");

			for (Set<IConnection> conset : conCollection) {
				for (IConnection conn : conset) {
					if (conn != null) {
						((IServiceCapableConnection) conn).invoke(
								"interviewStatus",
								new Object[] { interviewStatus }, this);
						log.debug("sendMessageWithClientByPublicSID interviewStatus"
								+ interviewStatus);

					}
				}
			}

			return true;

		} catch (Exception err) {
			log.debug("[startInterviewRecording]", err);
		}
		return null;
	}

	/**
	 * Get all ClientList Objects of that room and domain Used in
	 * lz.applyForModeration.lzx
	 * 
	 * @return
	 */
	public synchronized HashMap<String, RoomClient> getClientListScope() {
		HashMap<String, RoomClient> roomClientList = new HashMap<String, RoomClient>();
		try {
			IConnection current = Red5.getConnectionLocal();
			RoomClient currentClient = this.clientListManager
					.getClientByStreamId(current.getClient().getId());

			return this.clientListManager.getClientListByRoom(currentClient.getRoom_id());

		} catch (Exception err) {
			log.debug("[getClientListScope]", err);
		}
		return roomClientList;
	}

	private boolean getWhiteboardDrawStatus() {
		if (ScopeApplicationAdapter.whiteboardDrawStatus == null) {
			String drawStatus = cfgManagement.getConfValue("show.whiteboard.draw.status", String.class, "0");
			ScopeApplicationAdapter.whiteboardDrawStatus = "1".equals(drawStatus);
		}
		return ScopeApplicationAdapter.whiteboardDrawStatus;
	}
	
	public String getCryptKey() {
		try {

			if (ScopeApplicationAdapter.configKeyCryptClassName == null) {
				Configuration conf = cfgManagement.getConfKey(3,
						"crypt_ClassName");

				if (conf != null) {
					ScopeApplicationAdapter.configKeyCryptClassName = conf
							.getConf_value();
				}
			}

			return ScopeApplicationAdapter.configKeyCryptClassName;
		} catch (Exception err) {
			log.error("[getCryptKey]", err);
		}
		return null;
	}

    public String getExclusiveAudioKeyCode() {
        Configuration conf = cfgManagement.getConfKey(3, "exclusive.audio.keycode");
        if (null != conf) {
            return conf.getConf_value();
        } else {
            return null;
        }
    }

	public synchronized IScope getRoomScope(String room) {
		try {

			IScope globalScope = getContext().getGlobalScope();
			IScope webAppKeyScope = globalScope
					.getScope(OpenmeetingsVariables.webAppRootKey);

			String scopeName = "hibernate";
			// If set then its a NON default Scope
			if (room.length() != 0) {
				scopeName = room;
			}

			IScope scopeHibernate = webAppKeyScope.getScope(scopeName);

			return scopeHibernate;
		} catch (Exception err) {
			log.error("[getRoomScope]", err);
		}
		return null;
	}

    /*
	 * SIP transport methods
	 */

    public synchronized void updateSipTransport() {
        IConnection current = Red5.getConnectionLocal();
        String streamid = current.getClient().getId();
        RoomClient currentClient = this.clientListManager.getClientByStreamId(streamid);
        log.debug("getSipConferenceMembersNumber: " + roommanagement.getSipConferenceMembersNumber(currentClient.getRoom_id()));
        String newNumber = "("+Integer.toString(roommanagement.getSipConferenceMembersNumber(currentClient.getRoom_id())-1)+")";
        if(!newNumber.equals(currentClient.getLastname())) {
            currentClient.setLastname(newNumber);
            this.clientListManager.updateClientByStreamId(streamid, currentClient);
            log.debug("updateSipTransport: {}, {}, {}, {}", new Object[]{currentClient.getPublicSID(),
                    currentClient.getRoom_id(), currentClient.getFirstname(), currentClient.getLastname()});
            sendMessageWithClient(new String[]{"personal",currentClient.getFirstname(),currentClient.getLastname()});
        }
    }

    /**
     * Perform call to specified phone number and join to conference
     * @param number to call
     */
    public synchronized void joinToConfCall(String number) {
        IConnection current = Red5.getConnectionLocal();
        String streamid = current.getClient().getId();
        RoomClient currentClient = this.clientListManager.getClientByStreamId(streamid);
        Rooms rooms = roommanagement.getRoomById(currentClient.getRoom_id());
        log.debug("asterisk -rx \"originate Local/" + number + "@rooms extension " + rooms.getSipNumber() + "@rooms\"");
        try {
            Runtime.getRuntime().exec(new String[]{"asterisk", "-rx", "originate Local/" + number + "@rooms extension " + rooms.getSipNumber() + "@rooms"});
        } catch (IOException e) {
            log.error("Executing asterisk originate error: ", e);
        }
    }

    public synchronized String getSipNumber(Long room_id) {
        Rooms rooms = roommanagement.getRoomById(room_id);
        if(rooms != null) {
            log.debug("getSipNumber: room_id: {}, sipNumber: {}", new Object[]{room_id, rooms.getSipNumber()});
            return rooms.getSipNumber();
        }
        return null;
    }

    public synchronized void setSipTransport(Long room_id, String publicSID, String broadCastId) {
        IConnection current = Red5.getConnectionLocal();
        String streamid = current.getClient().getId();
        // Notify all clients of the same scope (room)
        RoomClient currentClient = this.clientListManager.getClientByStreamId(streamid);
        currentClient.setRoom_id(room_id);
        currentClient.setRoomEnter(new Date());
        currentClient.setFirstname("SIP Transport");
        currentClient.setLastname("("+Integer.toString(roommanagement.getSipConferenceMembersNumber(room_id)-1)+")");
        currentClient.setBroadCastID(Long.parseLong(broadCastId));
        currentClient.setIsBroadcasting(true);
        currentClient.setPublicSID(publicSID);
        currentClient.setAvsettings("av");
        currentClient.setVWidth(120);
        currentClient.setVHeight(90);
        this.clientListManager.updateClientByStreamId(streamid, currentClient);

        Collection<Set<IConnection>> conCollection = current
                .getScope().getConnections();
        for (Set<IConnection> conset : conCollection) {
            for (IConnection conn : conset) {
                if (conn != null) {
                    RoomClient rcl = this.clientListManager.getClientByStreamId(conn.getClient().getId());
                    if (rcl == null) {
                        // continue;
                    } else if (rcl.getIsScreenClient() != null
                            && rcl.getIsScreenClient()) {
                        // continue;
                    } else {
                        if (!streamid.equals(rcl.getStreamid())) {
                            // It is not needed to send back
                            // that event to the actuall
                            // Moderator
                            // as it will be already triggered
                            // in the result of this Function
                            // in the Client
                            if (conn instanceof IServiceCapableConnection) {
                                ((IServiceCapableConnection) conn).invoke("addNewUser", new Object[]{currentClient}, this);
                                ((IServiceCapableConnection) conn).invoke("newStream", new Object[]{currentClient}, this);
                                log.debug("sending setSipTransport to "
                                        + conn);
                            }
                        }
                    }
                }
            }
        }
    }
}
