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

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 javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.TypedQuery;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;

import org.openmeetings.app.conference.session.RoomClient;
import org.openmeetings.app.data.basic.AuthLevelmanagement;
import org.openmeetings.app.data.basic.Configurationmanagement;
import org.openmeetings.app.data.beans.basic.SearchResult;
import org.openmeetings.app.data.conference.dao.RoomModeratorsDaoImpl;
import org.openmeetings.app.data.user.Organisationmanagement;
import org.openmeetings.app.data.user.dao.UsersDaoImpl;
import org.openmeetings.app.persistence.beans.basic.Configuration;
import org.openmeetings.app.persistence.beans.domain.Organisation_Users;
import org.openmeetings.app.persistence.beans.rooms.RoomTypes;
import org.openmeetings.app.persistence.beans.rooms.Rooms;
import org.openmeetings.app.persistence.beans.rooms.Rooms_Organisation;
import org.openmeetings.app.persistence.beans.sip.OpenXGReturnObject;
import org.openmeetings.app.persistence.beans.user.Users;
import org.openmeetings.app.remote.red5.ClientListManager;
import org.openmeetings.app.sip.api.impl.asterisk.AsteriskDbSipClient;
import org.openmeetings.app.sip.api.request.SIPCreateConferenceRequest;
import org.openmeetings.app.sip.api.result.SipCreateConferenceRequestResult;
import org.openmeetings.app.sip.xmlrpc.OpenXGHttpClient;
import org.red5.logging.Red5LoggerFactory;
import org.slf4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;

/**
 * 
 * @author swagner
 * 
 */
@Transactional
public class Roommanagement {

	private static final Logger log = Red5LoggerFactory
			.getLogger(Roommanagement.class);

	@PersistenceContext
	private EntityManager em;

	@Autowired
	private Organisationmanagement organisationmanagement;
	@Autowired
	private OpenXGHttpClient openXGHttpClient;
	@Autowired
	private AsteriskDbSipClient asteriskDbSipClient;
	@Autowired
	private RoomModeratorsDaoImpl roomModeratorsDao;
	@Autowired
	private UsersDaoImpl usersDao;
	@Autowired
	private AuthLevelmanagement authLevelManagement;
	@Autowired
	private ClientListManager clientListManager;
    @Autowired
	private Configurationmanagement cfgManagement;

	/**
	 * add a new Record to the table roomtypes
	 * 
	 * @param name
	 * @return ID of new created roomtype or null
	 */
	public Long addRoomType(String name, boolean deleted) {
		try {
			RoomTypes rtype = new RoomTypes();
			rtype.setName(name);
			rtype.setStarttime(new Date());
			rtype.setDeleted(deleted ? "true" : "false");
			rtype = em.merge(rtype);
			long returnId = rtype.getRoomtypes_id();
			return returnId;
		} catch (Exception ex2) {
			log.error("[addRoomType] ", ex2);
		}
		return null;
	}

	public Long addRoom(Rooms room) {
		try {
            /* Red5SIP integration *******************************************************************************/
            Configuration conf = cfgManagement.getConfKey(3L, "red5sip.enable");
            if(conf != null && conf.getConf_value().equals("yes")) {
                if(room.getSipNumber() != null && !room.getSipNumber().isEmpty()) {
                    asteriskDbSipClient.createSIPConference(new SIPCreateConferenceRequest(room.getSipNumber()));
                } else {
                    SipCreateConferenceRequestResult requestResult = asteriskDbSipClient.createSIPConference(new SIPCreateConferenceRequest());
                    if(!requestResult.hasError()) {
                        room.setSipNumber(requestResult.getConferenceNumber());
                        room.setConferencePin(requestResult.getConferencePin());
                    }
                }
            }
            /*****************************************************************************************************/
			room.setStarttime(new Date());
			room = em.merge(room);
			long returnId = room.getRooms_id();
			return returnId;
		} catch (Exception ex2) {
			log.error("[addRoomType] ", ex2);
		}
		return null;
	}

	/**
	 * get all availible RoomTypes
	 * 
	 * @return List of RoomTypes
	 */
	public List<RoomTypes> getAllRoomTypes(Long user_level) {
		try {
			if (authLevelManagement.checkUserLevel(user_level)) {
				TypedQuery<RoomTypes> query = em
						.createQuery("select c from RoomTypes as c where c.deleted <> :deleted", RoomTypes.class);
				query.setParameter("deleted", "true");
				List<RoomTypes> ll = query.getResultList();
				return ll;
			}
		} catch (Exception ex2) {
			log.error("[getAllRoomTypes] ", ex2);
		}
		return null;
	}

	/**
	 * Get a RoomTypes-Object by its id
	 * 
	 * @param roomtypes_id
	 * @return RoomTypes-Object or NULL
	 */
	public RoomTypes getRoomTypesById(long roomtypes_id) {
		try {
			TypedQuery<RoomTypes> query = em
					.createQuery("select c from RoomTypes as c where c.roomtypes_id = :roomtypes_id AND c.deleted <> :deleted", RoomTypes.class);
			query.setParameter("roomtypes_id", roomtypes_id);
			query.setParameter("deleted", "true");
			List<?> ll = query.getResultList();
			if (ll.size() > 0) {
				return (RoomTypes) ll.get(0);
			}
		} catch (Exception ex2) {
			log.error("[getRoomTypesById] ", ex2);
		}
		return null;
	}

	/**
	 * get a room object if user level
	 * 
	 * @param user_level
	 * @param rooms_id
	 * @return
	 */
	public Rooms getRoomById(long user_level, long rooms_id) {
		try {
			if (authLevelManagement.checkUserLevel(user_level)) {
				return this.getRoomById(rooms_id);
			} else
				log.error("getRoombyId : Userlevel" + user_level
						+ " not allowed");
		} catch (Exception ex2) {
			log.error("[getRoomById] ", ex2);
		}
		return null;
	}

	public Rooms getRoomWithCurrentUsersById(long user_level, long rooms_id) {
		try {
			if (authLevelManagement.checkUserLevel(user_level)) {
				Rooms room = this.getRoomById(rooms_id);

				if (room != null) {
					HashMap<String, RoomClient> map = clientListManager
							.getClientListByRoom(room.getRooms_id());

					room.setCurrentusers(new LinkedList<RoomClient>());

					for (Iterator<String> iter = map.keySet().iterator(); iter
							.hasNext();) {
						room.getCurrentusers().add(map.get(iter.next()));
					}

					return room;
				}
			}
		} catch (Exception ex2) {
			log.error("[getRoomWithCurrentUsersById] ", ex2);
		}
		return null;
	}

	/**
	 * Get a Rooms-Object or NULL
	 * 
	 * @param rooms_id
	 * @return Rooms-Object or NULL
	 */
	public Rooms getRoomById(long rooms_id) {
		log.debug("getRoombyId : " + rooms_id);
		try {

			if (rooms_id == 0) {
				return null;
			}

			String hql = "select c from Rooms as c where c.rooms_id = :rooms_id AND c.deleted <> :deleted";
			Rooms room = null;

			TypedQuery<Rooms> query = em.createQuery(hql, Rooms.class);
			query.setParameter("rooms_id", rooms_id);
			query.setParameter("deleted", "true");
			List<Rooms> ll = query.getResultList();
			if (ll.size() > 0) {
				room = ll.get(0);
			}

			if (room != null) {
				return room;
			} else {
				log.info("Could not find room " + rooms_id);
			}
		} catch (Exception ex2) {
			log.error("[getRoomById] ", ex2);
		}
		return null;
	}

	/**
	 * Get a Rooms-Object or NULL
	 * 
	 * @param externalRoomId
	 * @return Rooms-Object or NULL
	 */
	public Rooms getRoomByExternalId(Long externalRoomId,
			String externalRoomType, long roomtypes_id) {
		log.debug("getRoombyExternalId : " + externalRoomId + " - "
				+ externalRoomType + " - " + roomtypes_id);
		try {
			String hql = "select c from Rooms as c JOIN c.roomtype as rt "
					+ "where c.externalRoomId = :externalRoomId AND c.externalRoomType = :externalRoomType "
					+ "AND rt.roomtypes_id = :roomtypes_id AND c.deleted <> :deleted";
			TypedQuery<Rooms> query = em.createQuery(hql, Rooms.class);
			query.setParameter("externalRoomId", externalRoomId);
			query.setParameter("externalRoomType", externalRoomType);
			query.setParameter("roomtypes_id", roomtypes_id);
			query.setParameter("deleted", "true");
			List<?> ll = query.getResultList();
			if (ll.size() > 0) {
				return (Rooms) ll.get(0);
			} else {
				log.error("Could not find room " + externalRoomId);
			}
		} catch (Exception ex2) {
			log.error("[getRoomByExternalId] ", ex2);
		}
		return null;
	}

	public Rooms getRoomByExternalId(long user_level, Long externalRoomId,
			String externalRoomType, long roomtypes_id) {
		try {
			if (authLevelManagement.checkUserLevel(user_level)) {
				return this.getRoomByExternalId(externalRoomId,
						externalRoomType, roomtypes_id);
			} else
				log.error("getRoombyExternalId : Userlevel" + user_level
						+ " not allowed");
		} catch (Exception ex2) {
			log.error("[getRoomByExternalId] ", ex2);
		}
		return null;
	}

	public SearchResult<Rooms> getRooms(long user_level, int start, int max,
			String orderby, boolean asc, String search) {
		try {
			if (authLevelManagement.checkAdminLevel(user_level)) {
				SearchResult<Rooms> sResult = new SearchResult<Rooms>();
				sResult.setRecords(this.selectMaxFromRooms(search));
				sResult.setObjectName(Rooms.class.getName());
				sResult.setResult(this.getRoomsInternatlByHQL(start, max,
						orderby, asc, search));
				return sResult;
			}
		} catch (Exception ex2) {
			log.error("[getRooms] ", ex2);
		}
		return null;
	}

	public SearchResult<Rooms> getRoomsWithCurrentUsers(long user_level, int start,
			int max, String orderby, boolean asc) {
		try {
			if (authLevelManagement.checkAdminLevel(user_level)) {
				SearchResult<Rooms> sResult = new SearchResult<Rooms>();
				sResult.setRecords(this.selectMaxFromRooms(""));
				sResult.setObjectName(Rooms.class.getName());

				List<Rooms> rooms = this.getRoomsInternatl(start, max, orderby,
						asc);

				for (Rooms room : rooms) {

					HashMap<String, RoomClient> map = clientListManager
							.getClientListByRoom(room.getRooms_id());

					room.setCurrentusers(new LinkedList<RoomClient>());

					for (Iterator<String> iter = map.keySet().iterator(); iter
							.hasNext();) {
						room.getCurrentusers().add(map.get(iter.next()));
					}

				}

				sResult.setResult(rooms);
				return sResult;
			}
		} catch (Exception ex2) {
			log.error("[getRooms] ", ex2);
		}
		return null;
	}

	public List<Rooms> getRoomsWithCurrentUsersByList(long user_level,
			int start, int max, String orderby, boolean asc) {
		try {
			if (authLevelManagement.checkAdminLevel(user_level)) {

				List<Rooms> rooms = this.getRoomsInternatl(start, max, orderby,
						asc);

				for (Rooms room : rooms) {

					HashMap<String, RoomClient> map = clientListManager
							.getClientListByRoom(room.getRooms_id());

					room.setCurrentusers(new LinkedList<RoomClient>());

					for (Iterator<String> iter = map.keySet().iterator(); iter
							.hasNext();) {
						room.getCurrentusers().add(map.get(iter.next()));
					}

				}

				return rooms;

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

	public List<Rooms> getRoomsWithCurrentUsersByListAndType(long user_level,
			int start, int max, String orderby, boolean asc,
			String externalRoomType) {
		try {
			if (authLevelManagement.checkAdminLevel(user_level)) {

				List<Rooms> rooms = this.getRoomsInternatlbyType(start, max,
						orderby, asc, externalRoomType);

				for (Rooms room : rooms) {

					HashMap<String, RoomClient> map = clientListManager
							.getClientListByRoom(room.getRooms_id());

					room.setCurrentusers(new LinkedList<RoomClient>());

					for (Iterator<String> iter = map.keySet().iterator(); iter
							.hasNext();) {
						room.getCurrentusers().add(map.get(iter.next()));
					}

				}

				return rooms;

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

	public Long selectMaxFromRooms(String search) {
		try {
			String hql = "select count(c.rooms_id) from Rooms c "
					+ "where c.deleted <> 'true' " + "AND c.name LIKE :search ";

			if (search.length() == 0) {
				search = "%";
			} else {
				search = "%" + search + "%";
			}

			// get all users
			TypedQuery<Long> query = em.createQuery(hql, Long.class);
			query.setParameter("search", search);
			List<Long> ll = query.getResultList();
			log.debug("Number of records" + ll.get(0));
			return ll.get(0);
		} catch (Exception ex2) {
			log.error("[selectMaxFromRooms] ", ex2);
		}
		return null;
	}

	/**
	 * gets a list of all availible rooms
	 * 
	 * @param user_level
	 * @param start
	 * @param max
	 * @param orderby
	 * @param asc
	 * @return
	 */
	public List<Rooms> getRoomsInternatl(int start, int max, String orderby,
			boolean asc) {
		try {
			CriteriaBuilder cb = em.getCriteriaBuilder();
			CriteriaQuery<Rooms> cq = cb.createQuery(Rooms.class);
			Root<Rooms> c = cq.from(Rooms.class);
			Predicate condition = cb.equal(c.get("deleted"), "false");
			cq.where(condition);
			cq.distinct(asc);
			if (asc) {
				cq.orderBy(cb.asc(c.get(orderby)));
			} else {
				cq.orderBy(cb.desc(c.get(orderby)));
			}
			TypedQuery<Rooms> q = em.createQuery(cq);
			q.setFirstResult(start);
			q.setMaxResults(max);
			List<Rooms> ll = q.getResultList();
			return ll;
		} catch (Exception ex2) {
			log.error("[getRooms ] ", ex2);
		}
		return null;
	}

	/**
	 * gets a list of all availible rooms
	 * 
	 * @param user_level
	 * @param start
	 * @param max
	 * @param orderby
	 * @param asc
	 * @return
	 */
	public List<Rooms> getRoomsInternatlByHQL(int start, int max,
			String orderby, boolean asc, String search) {
		try {

			String hql = "select c from Rooms c "
					+ "where c.deleted <> 'true' " + "AND c.name LIKE :search ";

			if (search.length() == 0) {
				search = "%";
			} else {
				search = "%" + search + "%";
			}
			if (orderby != null) {
				hql += " ORDER BY " + (orderby.startsWith("c.") ? "" : "c.") + orderby;
	
				if (asc) {
					hql += " ASC";
				} else {
					hql += " DESC";
				}
			}
			TypedQuery<Rooms> query = em.createQuery(hql, Rooms.class);
			query.setParameter("search", search);
			query.setFirstResult(start);
			query.setMaxResults(max);

			return query.getResultList();

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

	public List<Rooms> getAllRooms() {
		try {
			CriteriaBuilder cb = em.getCriteriaBuilder();
			CriteriaQuery<Rooms> cq = cb.createQuery(Rooms.class);
			Root<Rooms> c = cq.from(Rooms.class);
			Predicate condition = cb.equal(c.get("deleted"), "false");
			cq.where(condition);
			TypedQuery<Rooms> q = em.createQuery(cq);
			List<Rooms> ll = q.getResultList();
			return ll;
		} catch (Exception ex2) {
			log.error("[getAllRooms]", ex2);
		}
		return null;
	}

	public List<Rooms> getBackupRooms() {
		try {
			CriteriaBuilder cb = em.getCriteriaBuilder();
			CriteriaQuery<Rooms> cq = cb.createQuery(Rooms.class);
			cq.from(Rooms.class);
			TypedQuery<Rooms> q = em.createQuery(cq);
			List<Rooms> ll = q.getResultList();
			return ll;
		} catch (Exception ex2) {
			log.error("[getBackupRooms]", ex2);
		}
		return null;
	}

	public List<Rooms> getRoomsInternatlbyType(int start, int max,
			String orderby, boolean asc, String externalRoomType) {
		try {
			CriteriaBuilder cb = em.getCriteriaBuilder();
			CriteriaQuery<Rooms> cq = cb.createQuery(Rooms.class);
			Root<Rooms> c = cq.from(Rooms.class);
			Predicate condition = cb.equal(c.get("deleted"), "false");
			Predicate subCondition = cb.equal(c.get("externalRoomType"),
					externalRoomType);
			cq.where(condition, subCondition);
			cq.distinct(asc);
			if (asc) {
				cq.orderBy(cb.asc(c.get(orderby)));
			} else {
				cq.orderBy(cb.desc(c.get(orderby)));
			}
			TypedQuery<Rooms> q = em.createQuery(cq);
			q.setFirstResult(start);
			q.setMaxResults(max);
			List<Rooms> ll = q.getResultList();
			return ll;
		} catch (Exception ex2) {
			log.error("[getRooms ] ", ex2);
		}
		return null;
	}

	public List<Rooms_Organisation> getOrganisationsByRoom(long user_level,
			long rooms_id) {
		try {
			if (authLevelManagement.checkUserLevel(user_level)) {
				String hql = "select c from Rooms_Organisation as c "
						+ "where c.room.rooms_id = :rooms_id "
						+ "AND c.deleted <> :deleted";
				TypedQuery<Rooms_Organisation> q = em.createQuery(hql, Rooms_Organisation.class);

				q.setParameter("rooms_id", rooms_id);
				q.setParameter("deleted", "true");
				List<Rooms_Organisation> ll = q.getResultList();
				return ll;
			}
		} catch (Exception ex2) {
			log.error("[getOrganisationsByRoom] ", ex2);
		}
		return null;
	}

	/**
	 * get all rooms which are availible for public
	 * 
	 * @param user_level
	 * @param roomtypes_id
	 * @return
	 */
	public List<Rooms> getPublicRooms(long user_level, long roomtypes_id) {
		try {
			if (authLevelManagement.checkUserLevel(user_level)) {
				String queryString = "SELECT r from Rooms r "
						+ "JOIN r.roomtype as rt "
						+ "WHERE "
						+ "r.ispublic=:ispublic and r.deleted=:deleted and rt.roomtypes_id=:roomtypes_id";
				TypedQuery<Rooms> q = em.createQuery(queryString, Rooms.class);
				//
				q.setParameter("ispublic", true);
				q.setParameter("deleted", "false");
				q.setParameter("roomtypes_id", new Long(roomtypes_id));

				List<Rooms> ll = q.getResultList();

				return ll;
			}
		} catch (Exception ex2) {
			log.error("[getRoomsByOrganisation] ", ex2);
		}
		return null;
	}

	public List<Rooms> getRoomsByIds(List<Integer> roomIds) {
		try {
			if (roomIds == null || roomIds.size() == 0) {
				return new LinkedList<Rooms>();
			}

			String queryString = "SELECT r from Rooms r " + "WHERE ";

			queryString += "(";

			int i = 0;
			for (Integer room_id : roomIds) {
				if (i != 0) {
					queryString += " OR ";
				}
				queryString += " r.rooms_id = " + room_id;
				i++;
			}

			queryString += ")";

			TypedQuery<Rooms> q = em.createQuery(queryString, Rooms.class);

			List<Rooms> ll = q.getResultList();

			return ll;

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

	public List<Rooms> getPublicRoomsWithoutType(long user_level) {
		try {
			if (authLevelManagement.checkUserLevel(user_level)) {

				String queryString = "SELECT r from Rooms r " + "WHERE "
						+ "r.ispublic = :ispublic and r.deleted <> :deleted "
						+ "ORDER BY r.name ASC";

				TypedQuery<Rooms> q = em.createQuery(queryString, Rooms.class);

				q.setParameter("ispublic", true);
				q.setParameter("deleted", "true");
				List<Rooms> ll = q.getResultList();

				return ll;
			}
		} catch (Exception ex2) {
			log.error("[getPublicRoomsWithoutType] ", ex2);
			ex2.printStackTrace();
		}
		return null;
	}

	/**
	 * Get Appointed Meetings
	 */
	// ---------------------------------------------------------------------------------------------
	public List<Rooms> getAppointedMeetings(Long userid, Long user_level) {
		log.debug("Roommanagement.getAppointedMeetings");

		try {
			if (authLevelManagement.checkUserLevel(user_level)) {

				String queryString = "SELECT r from Rooms r "
						+ "JOIN r.roomtype as rt " + "WHERE "
						+ "r.deleted=:deleted and r.appointment=:appointed";
				TypedQuery<Rooms> q = em.createQuery(queryString, Rooms.class);
				//
				q.setParameter("appointed", true);
				q.setParameter("deleted", "false");

				List<Rooms> ll = q.getResultList();

				return ll;
			}
		} catch (Exception ex2) {
			log.error("[getAppointedMeetings] ", ex2);
		}
		return null;

	}

	// ---------------------------------------------------------------------------------------------

	/**
	 * get all rooms which are availible for public
	 * 
	 * @param user_level
	 * @param roomtypes_id
	 * @return
	 */
	public List<Rooms> getPublicRooms(long user_level) {
		try {
			if (authLevelManagement.checkUserLevel(user_level)) {
				// log.error("### getPublicRooms: create Query "+roomtypes_id);
				String queryString = "SELECT r from Rooms r "
						+ "JOIN r.roomtype as rt " + "WHERE "
						+ "r.ispublic=:ispublic and r.deleted=:deleted";
				TypedQuery<Rooms> q = em.createQuery(queryString, Rooms.class);
				//
				q.setParameter("ispublic", true);
				q.setParameter("deleted", "false");

				List<Rooms> ll = q.getResultList();
				return ll;
			}
		} catch (Exception ex2) {
			log.error("[getRoomsByOrganisation] ", ex2);
		}
		return null;
	}

    /**
     * Returns number of SIP conference participants
     * @param rooms_id id of room
     * @return number of participants
     */
    public Integer getSipConferenceMembersNumber(Long rooms_id) {
        Configuration conf = cfgManagement.getConfKey(3L, "red5sip.enable");
        if(conf != null && conf.getConf_value().equals("yes")) {
            Rooms rooms = this.getRoomById(rooms_id);
            if(rooms != null) {
                return asteriskDbSipClient.getConferenceMembersNumber(rooms.getSipNumber());
            } else {
                return 0;
            }
        } else {
            return null;
        }
    }

	/**
	 * adds a new Record to the table rooms
	 * @param name
	 * @param roomtypes_id
	 * @param ispublic
	 * @param hideActivitiesAndActions TODO
	 * @param hideFilesExplorer TODO
	 * @param hideActionsMenu TODO
	 * @param hideScreenSharing TODO
	 * @param hideWhiteboard TODO
	 * @return id of the newly created room or NULL
	 */
	public Long addRoom(long user_level, String name, long roomtypes_id,
			String comment, Long numberOfPartizipants, boolean ispublic,
			List<Integer> organisations, Boolean appointment, Boolean isDemoRoom,
			Integer demoTime, Boolean isModeratedRoom,
			List<Map<String, Object>> roomModerators,
			Boolean allowUserQuestions, Boolean isAudioOnly, Boolean isClosed,
			String redirectURL, String sipNumber, String conferencePin,
			Long ownerId, Boolean waitForRecording, Boolean allowRecording,
			Boolean hideTopBar, Boolean hideChat, Boolean hideActivitiesAndActions, Boolean hideFilesExplorer, 
			Boolean hideActionsMenu, Boolean hideScreenSharing, Boolean hideWhiteboard,
			Boolean showMicrophoneStatus) {

		try {
			if (authLevelManagement.checkAdminLevel(user_level)) {

				Rooms r = new Rooms();
				r.setName(name);
				r.setComment(comment);
				r.setStarttime(new Date());
				r.setNumberOfPartizipants(numberOfPartizipants);
				r.setRoomtype(this.getRoomTypesById(roomtypes_id));
				r.setIspublic(ispublic);
				r.setAllowUserQuestions(allowUserQuestions);
				r.setIsAudioOnly(isAudioOnly);

				r.setAppointment(appointment);

				r.setIsDemoRoom(isDemoRoom);
				r.setDemoTime(demoTime);

				r.setIsModeratedRoom(isModeratedRoom);
				r.setHideTopBar(hideTopBar);

				r.setDeleted("false");

				r.setIsClosed(isClosed);
				r.setRedirectURL(redirectURL);

				r.setSipNumber(sipNumber);
				r.setConferencePin(conferencePin);
				r.setOwnerId(ownerId);

				r.setWaitForRecording(waitForRecording);
				r.setAllowRecording(allowRecording);
				
				r.setHideChat(hideChat);
				r.setHideActivitiesAndActions(hideActivitiesAndActions);
				r.setHideActionsMenu(hideActionsMenu);
				r.setHideFilesExplorer(hideFilesExplorer);
				r.setHideScreenSharing(hideScreenSharing);	
				r.setHideWhiteboard(hideWhiteboard);
				r.setShowMicrophoneStatus(showMicrophoneStatus);
				
				// handle SIP Issues
				OpenXGReturnObject openXGReturnObject = openXGHttpClient
						.openSIPgCreateConference();

				if (openXGReturnObject != null) {
					r.setSipNumber(openXGReturnObject.getConferenceNumber());
					r.setConferencePin(openXGReturnObject.getConferencePin());
				}

                /* Red5SIP integration *******************************************************************************/
                Configuration conf = cfgManagement.getConfKey(3L, "red5sip.enable");
                if(conf != null && conf.getConf_value().equals("yes")) {
                    SipCreateConferenceRequestResult requestResult = asteriskDbSipClient
                            .createSIPConference(new SIPCreateConferenceRequest(sipNumber));

                    if(!requestResult.hasError()) {
                        r.setSipNumber(requestResult.getConferenceNumber());
                        r.setConferencePin(requestResult.getConferencePin());
                    }
                }
                /*****************************************************************************************************/

				r = em.merge(r);
				long returnId = r.getRooms_id();

				if (organisations != null) {
					Long t = this.updateRoomOrganisations(organisations, r);
					if (t == null)
						return null;
				}

				if (roomModerators != null) {
					roomModeratorsDao.addRoomModeratorByUserList(
							roomModerators, r.getRooms_id());
				}

				return returnId;
			}
		} catch (Exception ex2) {
			log.error("[addRoom] ", ex2);
		}
		return null;
	}

	public Long addRoomByMod(long user_level, String name, long roomtypes_id,
			String comment, Long numberOfPartizipants, boolean ispublic,
			Long organisation_id, Boolean appointment, Boolean isDemoRoom,
			Integer demoTime, Boolean isModeratedRoom,
			List<Map<String, Object>> roomModerators, Boolean allowUserQuestions) {

		log.debug("addRoom");

		try {
			if (authLevelManagement.checkModLevel(user_level)) {
				Rooms r = new Rooms();
				r.setName(name);
				r.setComment(comment);
				r.setStarttime(new Date());
				r.setNumberOfPartizipants(numberOfPartizipants);
				r.setRoomtype(this.getRoomTypesById(roomtypes_id));
				r.setIspublic(ispublic);

				r.setAllowUserQuestions(allowUserQuestions);
				r.setAppointment(appointment);

				r.setIsDemoRoom(isDemoRoom);
				r.setDemoTime(demoTime);

				r.setIsModeratedRoom(isModeratedRoom);

				r.setDeleted("false");
				r = em.merge(r);
				long returnId = r.getRooms_id();

				this.addRoomToOrganisation(3, returnId, organisation_id);

				if (roomModerators != null) {
					roomModeratorsDao.addRoomModeratorByUserList(
							roomModerators, r.getRooms_id());
				}

				return returnId;
			}
		} catch (Exception ex2) {
			log.error("[addRoom] ", ex2);
		}
		return null;
	}

	/**
	 * adds/check a new Record to the table rooms with external fields
	 * 
	 * @param name
	 * @param roomtypes_id
	 * @param ispublic
	 * @return id of (the newly created) room or NULL
	 */
	public Long addExternalRoom(String name, long roomtypes_id, String comment,
			Long numberOfPartizipants, boolean ispublic, List<Integer> organisations,
			Boolean appointment, Boolean isDemoRoom, Integer demoTime,
			Boolean isModeratedRoom, List<Map<String, Object>> roomModerators,
			Long externalRoomId, String externalRoomType,
			Boolean allowUserQuestions, Boolean isAudioOnly, Boolean isClosed,
			String redirectURL, Boolean waitForRecording,
			Boolean allowRecording, Boolean hideTopBar) {

		log.debug("addExternalRoom");

		try {
			Rooms r = new Rooms();
			r.setName(name);
			r.setComment(comment);
			r.setStarttime(new Date());
			r.setNumberOfPartizipants(numberOfPartizipants);
			r.setRoomtype(this.getRoomTypesById(roomtypes_id));
			r.setIspublic(ispublic);

			r.setAllowUserQuestions(allowUserQuestions);
			r.setIsAudioOnly(isAudioOnly);

			r.setAppointment(appointment);

			r.setIsDemoRoom(isDemoRoom);
			r.setDemoTime(demoTime);

			r.setIsModeratedRoom(isModeratedRoom);

			r.setDeleted("false");

			r.setExternalRoomId(externalRoomId);
			r.setExternalRoomType(externalRoomType);

			r.setIsClosed(isClosed);
			r.setRedirectURL(redirectURL);

			r.setWaitForRecording(waitForRecording);
			r.setAllowRecording(allowRecording);

			r.setHideTopBar(hideTopBar);

			r = em.merge(r);

			long returnId = r.getRooms_id();

			if (organisations != null) {
				Long t = this.updateRoomOrganisations(organisations, r);
				if (t == null)
					return null;
			}

			if (roomModerators != null) {
				roomModeratorsDao.addRoomModeratorByUserList(roomModerators,
						r.getRooms_id());
			}

			return returnId;
		} catch (Exception ex2) {
			log.error("[addExternalRoom] ", ex2);
		}
		return null;
	}

	/**
	 * adds a new record to the table rooms_organisation
	 * 
	 * @param rooms_id
	 * @param organisation_id
	 * @return the id of the newly created Rooms_Organisation or NULL
	 */
	public Long addRoomToOrganisation(long user_level, long rooms_id,
			long organisation_id) {
		try {
			if (authLevelManagement.checkAdminLevel(user_level)) {
				Rooms_Organisation rOrganisation = new Rooms_Organisation();
				rOrganisation.setRoom(this.getRoomById(rooms_id));
				log.debug("addRoomToOrganisation rooms '"
						+ rOrganisation.getRoom().getName() + "'");
				rOrganisation.setStarttime(new Date());
				rOrganisation.setOrganisation(organisationmanagement
						.getOrganisationById(organisation_id));
				rOrganisation.setDeleted("false");

				rOrganisation = em.merge(rOrganisation);
				long returnId = rOrganisation.getRooms_organisation_id();
				return returnId;
			}
		} catch (Exception ex2) {
			log.error("[addRoomToOrganisation] ", ex2);
		}
		return null;
	}

	public Long addRoomOrganisation(Rooms_Organisation rOrganisation) {
		try {

			rOrganisation.setStarttime(new Date());

			rOrganisation = em.merge(rOrganisation);
			long returnId = rOrganisation.getRooms_organisation_id();
			return returnId;

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

	/**
	 * 
	 * @param rooms_organisation_id
	 * @return
	 */
	public Rooms_Organisation getRoomsOrganisationById(
			long rooms_organisation_id) {
		try {
			CriteriaBuilder cb = em.getCriteriaBuilder();
			CriteriaQuery<Rooms_Organisation> cq = cb
					.createQuery(Rooms_Organisation.class);
			Root<Rooms_Organisation> c = cq.from(Rooms_Organisation.class);
			Predicate condition = cb.equal(c.get("rooms_organisation_id"),
					rooms_organisation_id);
			cq.where(condition);
			TypedQuery<Rooms_Organisation> q = em.createQuery(cq);
			List<Rooms_Organisation> ll = q.getResultList();

			if (ll.size() > 0) {
				return ll.get(0);
			}
		} catch (Exception ex2) {
			log.error("[getRoomsByOrganisation] ", ex2);
		}
		return null;
	}

	/**
	 * get List of Rooms_Organisation by organisation and roomtype
	 * 
	 * @param user_level
	 * @param organisation_id
	 * @param roomtypes_id
	 * @return
	 */
	public List<Rooms_Organisation> getRoomsOrganisationByOrganisationIdAndRoomType(
			long user_level, long organisation_id, long roomtypes_id) {
		try {
			if (authLevelManagement.checkUserLevel(user_level)) {
				String hql = "select c from Rooms_Organisation as c "
						+ "where c.room.roomtypes_id = :roomtypes_id "
						+ "AND c.organisation.organisation_id = :organisation_id "
						+ "AND c.deleted <> :deleted";
				TypedQuery<Rooms_Organisation> q = em.createQuery(hql, Rooms_Organisation.class);

				q.setParameter("roomtypes_id", roomtypes_id);
				q.setParameter("organisation_id", organisation_id);
				q.setParameter("deleted", "true");
				List<Rooms_Organisation> ll = q.getResultList();

				return ll;
			} else {
				log.error("[notauthentificated] " + user_level);
			}
		} catch (Exception ex2) {
			log.error("[getRoomsByOrganisation] ", ex2);
		}
		return null;
	}

	/**
	 * Gets all rooms by an organisation
	 * 
	 * @param organisation_id
	 * @return list of Rooms_Organisation with Rooms as Sub-Objects or null
	 */
	public List<Rooms_Organisation> getRoomsOrganisationByOrganisationId(
			long user_level, long organisation_id) {
		try {
			if (authLevelManagement.checkUserLevel(user_level)) {

				String hql = "SELECT c FROM Rooms_Organisation c "
						+ "WHERE c.organisation.organisation_id = :organisation_id "
						+ "AND c.deleted <> :deleted AND c.room.deleted <> :deleted "
						+ "AND c.organisation.deleted <> :deleted "
						+ "ORDER BY c.room.name ASC";

				TypedQuery<Rooms_Organisation> query = em.createQuery(hql, Rooms_Organisation.class);

				query.setParameter("organisation_id", organisation_id);
				query.setParameter("deleted", "true");

				List<Rooms_Organisation> ll = query.getResultList();

				return ll;
			} else {
				log.error("[notauthentificated] " + user_level);
			}
		} catch (Exception ex2) {
			log.error("[getPublicRoomsWithoutType] ", ex2);
			ex2.printStackTrace();
		}
		return null;
	}

	public SearchResult<Rooms_Organisation> getRoomsOrganisationByOrganisationId(long user_level,
			long organisation_id, int start, int max, String orderby,
			boolean asc) {
		try {
			if (authLevelManagement.checkModLevel(user_level)) {

				SearchResult<Rooms_Organisation> sResult = new SearchResult<Rooms_Organisation>();
				sResult.setObjectName(Rooms_Organisation.class.getName());
				sResult.setRecords(this.selectMaxFromRoomsByOrganisation(
						organisation_id).longValue());
				sResult.setResult(this.getRoomsOrganisationByOrganisationId(
						organisation_id, start, max, orderby, asc));
				return sResult;
			}
		} catch (Exception ex2) {
			log.error("[getRoomsByOrganisation] ", ex2);
		}
		return null;
	}

	public Integer selectMaxFromRoomsByOrganisation(long organisation_id) {
		try {
			// get all users
			String hql = "select c from Rooms_Organisation as c "
					+ "where c.organisation.organisation_id = :organisation_id "
					+ "AND c.deleted <> :deleted";
			TypedQuery<Rooms_Organisation> q = em.createQuery(hql, Rooms_Organisation.class);

			q.setParameter("organisation_id", organisation_id);
			q.setParameter("deleted", "true");
			List<Rooms_Organisation> ll = q.getResultList();

			return ll.size();
		} catch (Exception ex2) {
			log.error("[selectMaxFromRooms] ", ex2);
		}
		return null;
	}

	/**
	 * 
	 * @param organisation_id
	 * @param start
	 * @param max
	 * @param orderby
	 * @param asc
	 * @return
	 */
	private List<Rooms_Organisation> getRoomsOrganisationByOrganisationId(
			long organisation_id, int start, int max, String orderby,
			boolean asc) {
		try {
			String hql = "select c from Rooms_Organisation as c "
					+ "where c.organisation.organisation_id = :organisation_id "
					+ "AND c.deleted <> :deleted";
			if (orderby.startsWith("c.")) {
				hql += "ORDER BY " + orderby;
			} else {
				hql += "ORDER BY " + "c." + orderby;
			}
			if (asc) {
				hql += " ASC";
			} else {
				hql += " DESC";
			}

			TypedQuery<Rooms_Organisation> q = em.createQuery(hql, Rooms_Organisation.class);

			q.setParameter("organisation_id", organisation_id);
			q.setParameter("deleted", "true");
			q.setFirstResult(start);
			q.setMaxResults(max);
			List<Rooms_Organisation> ll = q.getResultList();

			return ll;
		} catch (Exception ex2) {
			log.error("[getRoomsByOrganisation] ", ex2);
		}
		return null;
	}

	private Rooms_Organisation getRoomsOrganisationByOrganisationIdAndRoomId(
			long organisation_id, long rooms_id) {
		try {
			String hql = "select c from Rooms_Organisation as c "
					+ "where c.room.rooms_id = :rooms_id "
					+ "AND c.organisation.organisation_id = :organisation_id "
					+ "AND c.deleted <> :deleted";
			TypedQuery<Rooms_Organisation> q = em.createQuery(hql, Rooms_Organisation.class);

			q.setParameter("rooms_id", rooms_id);
			q.setParameter("organisation_id", organisation_id);
			q.setParameter("deleted", "true");
			List<Rooms_Organisation> ll = q.getResultList();

			if (ll.size() > 0) {
				return ll.get(0);
			}
		} catch (Exception ex2) {
			log.error("[getRoomsOrganisationByOrganisationIdAndRoomId] ", ex2);
		}
		return null;
	}

	/**
	 * 
	 * @param organisation_id
	 * @return
	 */
	public List<Rooms_Organisation> getRoomsOrganisationByRoomsId(long rooms_id) {
		try {
			String hql = "select c from Rooms_Organisation as c "
					+ "where c.room.rooms_id = :rooms_id "
					+ "AND c.deleted <> :deleted";
			TypedQuery<Rooms_Organisation> q = em.createQuery(hql, Rooms_Organisation.class);

			q.setParameter("rooms_id", rooms_id);
			q.setParameter("deleted", "true");
			List<Rooms_Organisation> ll = q.getResultList();
			return ll;
		} catch (Exception ex2) {
			log.error("[getRoomsByOrganisation] ", ex2);
		}
		return null;
	}

	public List<Rooms_Organisation> getRoomsOrganisations() {
		try {
			CriteriaBuilder cb = em.getCriteriaBuilder();
			CriteriaQuery<Rooms_Organisation> cq = cb
					.createQuery(Rooms_Organisation.class);
			cq.from(Rooms_Organisation.class);
			TypedQuery<Rooms_Organisation> q = em.createQuery(cq);
			List<Rooms_Organisation> ll = q.getResultList();
			return ll;
		} catch (Exception ex2) {
			log.error("[getRoomsByOrganisation] ", ex2);
		}
		return null;
	}

	/**
	 * 
	 * @param user_id
	 * @param rooms_id
	 * @return
	 */
	private boolean checkUserOrgRoom(long user_id, long rooms_id) {
		try {

			Users us = usersDao.getUser(user_id);
			List<Organisation_Users> s = us.getOrganisation_users();

			for (Iterator<Organisation_Users> it = s.iterator(); it.hasNext();) {
				Organisation_Users orgUsers = it.next();
				long organisation_id = orgUsers.getOrganisation()
						.getOrganisation_id();
				List<Rooms_Organisation> ll = this
						.getRoomsOrganisationByOrganisationId(3,
								organisation_id);
				for (Iterator<Rooms_Organisation> it2 = ll.iterator(); it2
						.hasNext();) {
					Rooms_Organisation roomOrg = it2.next();
					if (roomOrg.getRoom().getRooms_id() == rooms_id) {
						return true;
					}
				}
			}

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

	/**
	 * 
	 * @param user_id
	 * @param user_level
	 * @param rooms_id
	 * @param roomtypes_id
	 * @param name
	 * @param ispublic
	 * @param comment
	 * @return
	 */
	public Rooms updateRoomsSelf(long user_id, long user_level, long rooms_id,
			long roomtypes_id, String name, boolean ispublic, String comment) {
		try {
			if (authLevelManagement.checkModLevel(user_level)) {

				if (this.checkUserOrgRoom(user_id, rooms_id)) {

					Rooms r = this.getRoomById(rooms_id);
					r.setComment(comment);
					r.setIspublic(ispublic);
					r.setName(name);
					r.setRoomtype(this.getRoomTypesById(roomtypes_id));
					r.setUpdatetime(new Date());

					if (r.getRooms_id() == null) {
						em.persist(r);
					} else {
						if (!em.contains(r)) {
							em.merge(r);
						}
					}
				}
			}
		} catch (Exception ex2) {
			log.error("[updateRoom] ", ex2);
		}
		return null;
	}

	/**
	 * Update a Record in the rooms table
	 * @param rooms_id
	 * @param roomtypes_id
	 * @param name
	 * @param ispublic
	 * @param comment
	 * @param hideActivitiesAndActions TODO
	 * @param hideFilesExplorer TODO
	 * @param hideActionsMenu TODO
	 * @param hideScreenSharing TODO
	 * @param hideWhiteboard TODO
	 * @return
	 */
	public Long updateRoom(long user_level, long rooms_id, long roomtypes_id,
			String name, boolean ispublic, String comment,
			Long numberOfPartizipants, List<Integer> organisations,
			Boolean appointment, Boolean isDemoRoom, Integer demoTime,
			Boolean isModeratedRoom, List<Map<String, Object>> roomModerators,
			Boolean allowUserQuestions, Boolean isAudioOnly, Boolean isClosed,
			String redirectURL, String sipNumber, String conferencePin,
			Long ownerId, Boolean waitForRecording, Boolean allowRecording,
			Boolean hideTopBar, Boolean hideChat, Boolean hideActivitiesAndActions, 
			Boolean hideFilesExplorer, Boolean hideActionsMenu, Boolean hideScreenSharing, Boolean hideWhiteboard,
			Boolean showMicrophoneStatus) {
		try {

			log.debug("*** updateRoom numberOfPartizipants: "
					+ numberOfPartizipants);
			if (authLevelManagement.checkAdminLevel(user_level)) {

				return this.updateRoomInternal(rooms_id, roomtypes_id, name,
						ispublic, comment, numberOfPartizipants, organisations,
						appointment, isDemoRoom, demoTime, isModeratedRoom,
						roomModerators, allowUserQuestions, isAudioOnly,
						isClosed, redirectURL, sipNumber, conferencePin,
						ownerId, waitForRecording, allowRecording, hideTopBar, hideChat, 
						hideActivitiesAndActions, hideFilesExplorer, hideActionsMenu, 
						hideScreenSharing, hideWhiteboard, showMicrophoneStatus);

			}

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

	public Long updateRoomInternal(long rooms_id, long roomtypes_id,
			String name, boolean ispublic, String comment,
			Long numberOfPartizipants, List<Integer> organisations,
			Boolean appointment, Boolean isDemoRoom, Integer demoTime,
			Boolean isModeratedRoom, List<Map<String, Object>> roomModerators,
			Boolean allowUserQuestions, Boolean isAudioOnly, Boolean isClosed,
			String redirectURL, String sipNumber, String conferencePin,
			Long ownerId, Boolean waitForRecording, Boolean allowRecording,
			Boolean hideTopBar, Boolean hideChat, Boolean hideActivitiesAndActions, Boolean hideFilesExplorer, 
			Boolean hideActionsMenu, Boolean hideScreenSharing, Boolean hideWhiteboard, 
			Boolean showMicrophoneStatus) {
		try {
			log.debug("*** updateRoom numberOfPartizipants: "
					+ numberOfPartizipants);
			Rooms r = this.getRoomById(rooms_id);
			r.setComment(comment);

			r.setIspublic(ispublic);
			r.setNumberOfPartizipants(numberOfPartizipants);
			r.setName(name);
			r.setRoomtype(this.getRoomTypesById(roomtypes_id));
			r.setUpdatetime(new Date());
			r.setAllowUserQuestions(allowUserQuestions);
			r.setIsAudioOnly(isAudioOnly);

			r.setIsDemoRoom(isDemoRoom);
			r.setDemoTime(demoTime);

			r.setAppointment(appointment);

			r.setIsModeratedRoom(isModeratedRoom);
			r.setHideTopBar(hideTopBar);

			r.setIsClosed(isClosed);
			r.setRedirectURL(redirectURL);

			r.setSipNumber(sipNumber);
			r.setConferencePin(conferencePin);
			r.setOwnerId(ownerId);

			r.setWaitForRecording(waitForRecording);
			r.setAllowRecording(allowRecording);
			
			r.setHideChat(hideChat);
			r.setHideActivitiesAndActions(hideActivitiesAndActions);
			r.setHideActionsMenu(hideActionsMenu);
			r.setHideFilesExplorer(hideFilesExplorer);
			r.setHideScreenSharing(hideScreenSharing);
			r.setHideWhiteboard(hideWhiteboard);
			r.setShowMicrophoneStatus(showMicrophoneStatus);

			if (r.getRooms_id() == null) {
				em.persist(r);
			} else {
				if (!em.contains(r)) {
					r = em.merge(r);
				}
			}

			if (organisations != null) {
				Long t = this.updateRoomOrganisations(organisations, r);
				if (t == null)
					return null;
			}
			if (roomModerators != null) {
				roomModeratorsDao.updateRoomModeratorByUserList(roomModerators,
						r.getRooms_id());
			}

			return r.getRooms_id();
		} catch (Exception ex2) {
			log.error("[updateRoom] ", ex2);
		}
		return null;
	}

	public Long updateRoomByMod(long user_level, long rooms_id,
			long roomtypes_id, String name, boolean ispublic, String comment,
			Long numberOfPartizipants, Long organisations, Boolean appointment,
			Boolean isDemoRoom, Integer demoTime, Boolean isModeratedRoom,
			List<Map<String, Object>> roomModerators, Boolean allowUserQuestions) {
		try {
			log.debug("*** updateRoom numberOfPartizipants: "
					+ numberOfPartizipants);
			if (authLevelManagement.checkModLevel(user_level)) {
				Rooms r = this.getRoomById(rooms_id);
				r.setComment(comment);

				r.setIspublic(ispublic);
				r.setNumberOfPartizipants(numberOfPartizipants);
				r.setName(name);
				r.setRoomtype(this.getRoomTypesById(roomtypes_id));
				r.setUpdatetime(new Date());
				r.setAllowUserQuestions(allowUserQuestions);

				r.setIsDemoRoom(isDemoRoom);
				r.setDemoTime(demoTime);

				r.setAppointment(appointment);

				r.setIsModeratedRoom(isModeratedRoom);

				if (r.getRooms_id() == null) {
					em.persist(r);
				} else {
					if (!em.contains(r)) {
						em.merge(r);
					}
				}

				// FIXME: Organizations will not be changed when you do an
				// update as Moderator

				if (roomModerators != null) {
					roomModeratorsDao.updateRoomModeratorByUserList(
							roomModerators, r.getRooms_id());
				}

				return r.getRooms_id();
			}
		} catch (Exception ex2) {
			log.error("[updateRoom] ", ex2);
		}
		return null;
	}

	@SuppressWarnings("rawtypes")
	private boolean checkRoomAlreadyInOrg(Long orgid, List organisations)
			throws Exception {
		for (Iterator it = organisations.iterator(); it.hasNext();) {
			Rooms_Organisation rOrganisation = (Rooms_Organisation) it.next();
			if (rOrganisation.getOrganisation().getOrganisation_id()
					.equals(orgid))
				return true;
		}
		return false;
	}

	private boolean checkRoomShouldByDeleted(long orgId, List<Integer> organisations) throws Exception {
		for (Iterator<Integer> it = organisations.iterator(); it.hasNext();) {
			Integer key = it.next();
			Long storedOrgId = key.longValue();
			if (storedOrgId.equals(orgId))
				return true;
		}
		return false;
	}

	private Long updateRoomOrganisations(List<Integer> organisations, Rooms room)
			throws Exception {
		List<Rooms_Organisation> roomOrganisations = this.getOrganisationsByRoom(3,
				room.getRooms_id());

		List<Long> roomsToAdd = new LinkedList<Long>();
		List<Long> roomsToDel = new LinkedList<Long>();

		for (Iterator<Integer> it = organisations.iterator(); it.hasNext();) {
			Integer key = it.next();
			Long orgIdToAdd = key.longValue();
			if (!this.checkRoomAlreadyInOrg(orgIdToAdd, roomOrganisations))
				roomsToAdd.add(orgIdToAdd);
		}

		for (Iterator<Rooms_Organisation> it = roomOrganisations.iterator(); it.hasNext();) {
			Rooms_Organisation rOrganisation = it.next();
			Long orgIdToDel = rOrganisation.getOrganisation()
					.getOrganisation_id();
			if (!this.checkRoomShouldByDeleted(orgIdToDel, organisations))
				roomsToDel.add(orgIdToDel);
		}

		// log.error("updateRoomOrganisations roomsToAdd: "+roomsToAdd.size());
		// log.error("updateRoomOrganisations roomsToDel: "+roomsToDel.size());

		for (Iterator<Long> it = roomsToAdd.iterator(); it.hasNext();) {
			Long orgIdToAdd = it.next();
			this.addRoomToOrganisation(3, room.getRooms_id(), orgIdToAdd);
		}
		for (Iterator<Long> it = roomsToDel.iterator(); it.hasNext();) {
			Long orgToDel = it.next();
			this.deleteRoomFromOrganisationByRoomAndOrganisation(
					room.getRooms_id(), orgToDel);
		}

		return new Long(1);
	}

	/**
	 * delete all Rooms_Organisations and Room by a given room_id
	 * 
	 * @param rooms_id
	 */
	public Long deleteRoomById(long user_level, long rooms_id) {
		try {
			if (authLevelManagement.checkAdminLevel(user_level)) {
				this.deleteAllRoomsOrganisationOfRoom(rooms_id);
				return this.deleteRoom(this.getRoomById(rooms_id));
			}
		} catch (Exception ex2) {
			log.error("[deleteRoomById] ", ex2);
		}
		return null;
	}

	/**
	 * deletes a Room by given Room-Object
	 * 
	 * @param r
	 */
	public Long deleteRoom(Rooms r) {
		log.debug("deleteRoom");
		try {
			r.setDeleted("true");
			r.setUpdatetime(new Date());
			if (r.getRooms_id() == null) {
				em.persist(r);
			} else {
				if (!em.contains(r)) {
					em.merge(r);
				}
			}
			return r.getRooms_id();
		} catch (Exception ex2) {
			log.error("[deleteRoomsOrganisation] ", ex2);
		}
		return null;
	}

	/**
	 * delete all Rooms_Organisation by a rooms_id
	 * 
	 * @param rooms_id
	 */
	@SuppressWarnings("rawtypes")
	public void deleteAllRoomsOrganisationOfRoom(long rooms_id) {
		try {
			List ll = this.getRoomsOrganisationByRoomsId(rooms_id);
			for (Iterator it = ll.iterator(); it.hasNext();) {
				Rooms_Organisation rOrg = (Rooms_Organisation) it.next();
				this.deleteRoomsOrganisation(rOrg);
			}
		} catch (Exception ex2) {
			log.error("[deleteAllRoomsOrganisationOfRoom] ", ex2);
		}
	}

	/**
	 * Delete all room of a given Organisation
	 * 
	 * @param organisation_id
	 */
	@SuppressWarnings("rawtypes")
	public void deleteAllRoomsOrganisationOfOrganisation(long organisation_id) {
		try {
			List ll = this.getRoomsOrganisationByOrganisationId(3,
					organisation_id);
			for (Iterator it = ll.iterator(); it.hasNext();) {
				Rooms_Organisation rOrg = (Rooms_Organisation) it.next();
				this.deleteRoomsOrganisation(rOrg);
			}
		} catch (Exception ex2) {
			log.error("[deleteAllRoomsOfOrganisation] ", ex2);
		}
	}

	/**
	 * Delete a Rooms_Organisation by its id
	 * 
	 * @param rooms_organisation_id
	 */
	public Long deleteRoomsOrganisationByID(long rooms_organisation_id) {
		try {
			Rooms_Organisation rOrg = this
					.getRoomsOrganisationById(rooms_organisation_id);
			return this.deleteRoomsOrganisation(rOrg);
		} catch (Exception ex2) {
			log.error("[deleteRoomsOrganisationByID] ", ex2);
		}
		return null;
	}

	private Long deleteRoomFromOrganisationByRoomAndOrganisation(long rooms_id,
			long organisation_id) {
		try {
			Rooms_Organisation rOrganisation = this
					.getRoomsOrganisationByOrganisationIdAndRoomId(
							organisation_id, rooms_id);
			return this.deleteRoomsOrganisation(rOrganisation);
		} catch (Exception ex2) {
			log.error("[deleteRoomFromOrganisationByRoomAndOrganisation] ", ex2);
		}
		return null;
	}

	/**
	 * delete a Rooms_Organisation-Object
	 * 
	 * @param rOrg
	 */
	public Long deleteRoomsOrganisation(Rooms_Organisation rOrg) {
		try {
			rOrg.setDeleted("true");
			rOrg.setUpdatetime(new Date());
			if (rOrg.getRooms_organisation_id() == null) {
				em.persist(rOrg);
			} else {
				if (!em.contains(rOrg)) {
					em.merge(rOrg);
				}
			}
			return rOrg.getRooms_organisation_id();
		} catch (Exception ex2) {
			log.error("[deleteRoomsOrganisation] ", ex2);
		}
		return null;
	}

	/**
	 * Update Room Object
	 */
	// --------------------------------------------------------------------------------------------
	public void updateRoomObject(Rooms room) {
		log.debug("updateRoomObject " + room.getIsClosed());

		try {
			if (room.getRooms_id() == null) {
				em.persist(room);
			} else {
				if (!em.contains(room)) {
					em.merge(room);
				}
			}
		} catch (Exception e) {
			log.error("Error updateRoomObject : ", e);
		}
	}

	// --------------------------------------------------------------------------------------------

	public void closeRoom(Long rooms_id, Boolean status) {
		try {

			Rooms room = this.getRoomById(rooms_id);

			room.setIsClosed(status);

			this.updateRoomObject(room);

		} catch (Exception e) {
			log.error("Error updateRoomObject : ", e);
		}
	}

	/**
	 * Get a Rooms-Object or NULL
	 * 
	 * @param rooms_id
	 * @return Rooms-Object or NULL
	 */
	public Rooms getRoomByOwnerAndTypeId(Long ownerId, Long roomtypesId,
			String roomName) {
		try {

			if (roomtypesId == null || roomtypesId == 0) {
				return null;
			}
			log.debug("getRoomByOwnerAndTypeId : " + ownerId + " || "
					+ roomtypesId);

			String hql = "select c from Rooms as c "
					+ "where c.ownerId = :ownerId "
					+ "AND c.roomtype.roomtypes_id = :roomtypesId "
					+ "AND c.deleted <> :deleted";

			Rooms room = null;

			TypedQuery<Rooms> query = em.createQuery(hql, Rooms.class);
			query.setParameter("ownerId", ownerId);
			query.setParameter("roomtypesId", roomtypesId);
			query.setParameter("deleted", "true");
			List<Rooms> ll = query.getResultList();
			if (ll.size() > 0) {
				room = ll.get(0);
			}

			if (room != null) {
				return room;
			} else {
				log.debug("Could not find room " + ownerId + " || "
						+ roomtypesId);
				
				Long rooms_id = this.addRoom(3L, roomName, roomtypesId,
						"My Rooms of ownerId " + ownerId,
						(roomtypesId == 1) ? 25L : 150L, // numberOfPartizipants
						false, // ispublic
						null, // organisations
						false, // appointment
						false, // isDemoRoom
						null, // demoTime
						false, // isModeratedRoom
						null, // roomModerators
						true, // allowUserQuestions
						false, // isAudioOnly
						false, // isClosed
						"", // redirectURL
						"", // sipNumber
						"", // conferencePin
						ownerId, null, null, 
						false, // hideTopBar
						false, // hideChat
						false, // hideActivitiesAndActions
						false, // hideFilesExplorer
						false, // hideActionsMenu
						false, // hideScreenSharing 
						false, // hideWhiteboard
						false //showMicrophoneStatus
						);

				if (rooms_id != null) {
					return this.getRoomById(rooms_id);
				}
			}
		} catch (Exception ex2) {
			log.error("[getRoomByOwnerAndTypeId] ", ex2);
		}
		return null;
	}

}
