/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License") +  you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */
package org.apache.openmeetings.session;

import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Date;
import java.util.LinkedList;
import java.util.List;
import java.util.Map.Entry;
import java.util.Random;

import org.apache.openmeetings.db.dao.server.ISessionManager;
import org.apache.openmeetings.db.dto.basic.SearchResult;
import org.apache.openmeetings.db.dto.server.ClientSessionInfo;
import org.apache.openmeetings.db.entity.room.Client;
import org.apache.openmeetings.db.entity.server.Server;
import org.apache.openmeetings.session.store.IClientPersistenceStore;
import org.apache.openmeetings.util.OpenmeetingsVariables;
import org.apache.openmeetings.util.crypt.ManageCryptStyle;
import org.red5.logging.Red5LoggerFactory;
import org.slf4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;

/**
 * Handle {@link Client} objects.
 * 
 * Use a kind of decorator pattern to inject the {@link Server} into every call.
 * 
 * @author sebawagner
 * 
 */
public class SessionManager implements ISessionManager {
	
	protected static final Logger log = Red5LoggerFactory.getLogger(
			SessionManager.class, OpenmeetingsVariables.webAppRootKey);
	
	@Autowired
	private ServerUtil serverUtil;
	
	/**
	 * Injected via Spring, needs a getter/setter because it can be configured
	 * Autowired will not suit here as there are multiple implementations of the
	 * {@link IClientPersistenceStore}
	 */
	private IClientPersistenceStore cache;
	
	public IClientPersistenceStore getCache() {
		return cache;
	}

	public void setCache(IClientPersistenceStore cache) {
		this.cache = cache;
	}

	private ISessionManager sessionManager = new ISessionManager() {
		
		public synchronized Client addClientListItem(String streamId,
				String scopeName, Integer remotePort, String remoteAddress,
				String swfUrl, boolean isAVClient, Server server) {
			try {

				// Store the Connection into a bean and add it to the HashMap
				Client rcm = new Client();
				rcm.setConnectedSince(new Date());
				rcm.setStreamid(streamId);
				rcm.setScope(scopeName);
				long random = System.currentTimeMillis() + new BigInteger(256, new Random()).longValue();
				
				rcm.setPublicSID(ManageCryptStyle.getInstanceOfCrypt()
						.createPassPhrase(String.valueOf(random).toString()));

				rcm.setServer(server);
				rcm.setUserport(remotePort);
				rcm.setUserip(remoteAddress);
				rcm.setSwfurl(swfUrl);
				rcm.setIsMod(new Boolean(false));
				rcm.setCanDraw(new Boolean(false));
				rcm.setIsAVClient(isAVClient);

				if (cache.containsKey(null, streamId)) {
					log.error("Tried to add an existing Client " + streamId);
					return null;
				}

				cache.put(rcm.getStreamid(), rcm);

				return rcm;
			} catch (Exception err) {
				log.error("[addClientListItem]", err);
			}
			return null;
		}

		public synchronized Collection<Client> getClients() {
			return cache.getClients();
		}
		
		public synchronized Collection<Client> getClientsWithServer() {
			return cache.getClientsWithServer();
		}

		public synchronized Client getClientByStreamId(String streamId, Server server) {
			try {
				if (!cache.containsKey(server, streamId)) {
					log.debug("Tried to get a non existing Client " + streamId + " server " + server);
					return null;
				}
				return cache.get(server, streamId);
			} catch (Exception err) {
				log.error("[getClientByStreamId]", err);
			}
			return null;
		}

		public Client getClientByPublicSID(String publicSID, boolean isAVClient, Server server) {
			try {
				for (Client rcl : cache.getClientsByPublicSID(server, publicSID)) {
					if (rcl.getIsAVClient() != isAVClient) {
						continue;
					}
					return rcl;
				}
			} catch (Exception err) {
				log.error("[getClientByPublicSID]", err);
			}
			return null;
		}
		
		public ClientSessionInfo getClientByPublicSIDAnyServer(String publicSID, boolean isAVClient) {
			try {
				for (Entry<Long,List<Client>> entry : cache.getClientsByPublicSID(publicSID).entrySet()) {
					for (Client rcl : entry.getValue()) {
						if (rcl.getIsAVClient() != isAVClient) {
							continue;
						}
						return new ClientSessionInfo(rcl, entry.getKey());
					}
				}
			} catch (Exception err) {
				log.error("[getClientByPublicSIDAnyServer]", err);
			}
			return null;
		}

		public synchronized Client getClientByUserId(Long userId) {
			try {
				for (Client rcl : cache.getClientsByUserId(null, userId)) {
					
					if (rcl.getIsScreenClient()) {
						continue;
					}
					
					if (rcl.getIsAVClient()) {
						continue;
					}
					
					return rcl;
				}
			} catch (Exception err) {
				log.error("[getClientByUserId]", err);
			}
			return null;
		}

		public synchronized Boolean updateAVClientByStreamId(String streamId, Client rcm, Server server) {
			try {
				// get the corresponding user session object and update the settings
				Client rclUsual = getClientByPublicSID(rcm.getPublicSID(), false, server);
				if (rclUsual != null) {
					rclUsual.setBroadCastID(rcm.getBroadCastID());
					rclUsual.setAvsettings(rcm.getAvsettings());
					rclUsual.setVHeight(rcm.getVHeight());
					rclUsual.setVWidth(rcm.getVWidth());
					rclUsual.setVX(rcm.getVX());
					rclUsual.setVY(rcm.getVY());
					Client rclSaved = cache.get(server, rclUsual.getStreamid());
					if (rclSaved != null) {
						cache.put(rclUsual.getStreamid(), rclUsual);
					} else {
						log.debug("Tried to update a non existing Client " + rclUsual.getStreamid());
					}
				}

				updateClientByStreamId(streamId, rcm, false, server);
			} catch (Exception err) {
				log.error("[updateAVClientByStreamId]", err);
			}
			return null;
		}

		public synchronized Boolean updateClientByStreamId(String streamId,
				Client rcm, boolean updateRoomCount, Server server) {
			try {
				
				Client rclSaved = cache.get(server, streamId);
				
				if (rclSaved != null) {
					cache.put(streamId, rcm);
					return true;
				} else {
					log.debug("Tried to update a non existing Client " + streamId);
					return false;
				}
			} catch (Exception err) {
				log.error("[updateClientByStreamId]", err);
			}
			return null;
		}

		public synchronized Boolean removeClient(String streamId, Server server) {
			try {
				if (cache.containsKey(server,streamId)) {
					cache.remove(server,streamId);
					return true;
				} else {
					log.debug("Tried to remove a non existing Client " + streamId);
					return false;
				}
			} catch (Exception err) {
				log.error("[removeClient]", err);
			}
			return null;
		}

		public synchronized ArrayList<Client> getClientListByRoom(Long roomId) {
			ArrayList<Client> roomClientList = new ArrayList<Client>();
			try {

				for (Client rcl : cache.getClientsByRoomId(roomId)) {

					if (rcl.getIsScreenClient()) {
						continue;
					}
					if (rcl.getIsAVClient()) {
						continue;
					}

					// Only parse really those users out that are really a full session object
					// and no pseudo session object like the audio/video or screen
					// sharing connection
					roomClientList.add(rcl);
				}
			} catch (Exception err) {
				log.error("[getClientListByRoom]", err);
			}
			return roomClientList;
		}
		
		public synchronized Collection<Client> getClientListByRoomAll(Long roomId) {
			try {
				return cache.getClientsByRoomId(roomId);
			} catch (Exception err) {
				log.error("[getClientListByRoomAll]", err);
			}
			return null;
		}

		public synchronized List<Client> getCurrentModeratorByRoom(Long room_id) {
			List<Client> rclList = new LinkedList<Client>();
			List<Client> currentClients = this.getClientListByRoom(room_id);
			for (Client rcl : currentClients) {
				if (rcl.getIsMod()) {
					rclList.add(rcl);
				}
			}

			return rclList;
		}

		// FIXME not sorted
		public synchronized SearchResult<Client> getListByStartAndMax(
				int start, int max, String orderby, boolean asc) {
			SearchResult<Client> sResult = new SearchResult<Client>();
			sResult.setObjectName(Client.class.getName());
			sResult.setRecords(Long.valueOf(cache.size()).longValue());
			sResult.setResult(cache.getClientsWithServer());
			return sResult;
		}

		public long getRecordingCount(long roomId) {
			List<Client> currentClients = this.getClientListByRoom(roomId);
			int numberOfRecordingUsers = 0;
			for (Client rcl : currentClients) {
				if (rcl.isStartRecording()) {
					numberOfRecordingUsers++;
				}
			}
			return numberOfRecordingUsers;
		}

		public long getPublishingCount(long roomId) {
			List<Client> currentClients = this.getClientListByRoom(roomId);
			int numberOfPublishingUsers = 0;
			for (Client rcl : currentClients) {
				if (rcl.isStreamPublishStarted()) {
					numberOfPublishingUsers++;
				}
			}
			return numberOfPublishingUsers;
		}
		
		public List<Long> getActiveRoomIdsByServer(Server server) {
			return cache.getRoomsIdsByServer(server);
		}
		
		
		public String getSessionStatistics() {
			return cache.getDebugInformation(Arrays.asList(IClientPersistenceStore.DEBUG_DETAILS.SIZE));
		}

		public void sessionStart() {
			// TODO Auto-generated method stub
			
		}
		
	};
	
	public Client addClientListItem(String streamId, String scopeName,
			Integer remotePort, String remoteAddress, String swfUrl,
			boolean isAVClient, Server server) {
		if (server == null) {
			server = serverUtil.getCurrentServer();
		}
		return sessionManager.addClientListItem(streamId, scopeName,
				remotePort, remoteAddress, swfUrl, isAVClient, server);
	}

	public Collection<Client> getClients() {
		return sessionManager.getClients();
	}
	
	public Collection<Client> getClientsWithServer() {
		return sessionManager.getClientsWithServer();
	}

	public Client getClientByStreamId(String streamId, Server server) {
		if (server == null) {
			server = serverUtil.getCurrentServer();
		}
		return sessionManager.getClientByStreamId(streamId, server);
	}

	public Client getClientByPublicSID(String publicSID, boolean isAVClient,
			Server server) {
		if (server == null) {
			server = serverUtil.getCurrentServer();
		}
		return sessionManager.getClientByPublicSID(publicSID, isAVClient,
				server);
	}

	public ClientSessionInfo getClientByPublicSIDAnyServer(String publicSID,
			boolean isAVClient) {
		return sessionManager.getClientByPublicSIDAnyServer(publicSID,
				isAVClient);
	}

	public Client getClientByUserId(Long userId) {
		return sessionManager.getClientByUserId(userId);
	}

	public Boolean updateAVClientByStreamId(String streamId, Client rcm, Server server) {
		if (server == null) {
			server = serverUtil.getCurrentServer();
		}
		return sessionManager.updateAVClientByStreamId(streamId, rcm, server);
	}

	public Boolean updateClientByStreamId(String streamId, Client rcm,
			boolean updateRoomCount, Server server) {
		if (server == null) {
			server = serverUtil.getCurrentServer();
		}
		return sessionManager.updateClientByStreamId(streamId, rcm,
				updateRoomCount, server);
	}

	public Boolean removeClient(String streamId, Server server) {
		if (server == null) {
			server = serverUtil.getCurrentServer();
		}
		return sessionManager.removeClient(streamId, server);
	}

	public List<Client> getClientListByRoom(Long room_id) {
		return sessionManager.getClientListByRoom(room_id);
	}

	public Collection<Client> getClientListByRoomAll(Long room_id) {
		return sessionManager.getClientListByRoomAll(room_id);
	}

	public List<Client> getCurrentModeratorByRoom(Long room_id) {
		return sessionManager.getCurrentModeratorByRoom(room_id);
	}

	public SearchResult<Client> getListByStartAndMax(int start, int max,
			String orderby, boolean asc) {
		return sessionManager.getListByStartAndMax(start, max, orderby, asc);
	}

	public long getRecordingCount(long roomId) {
		return sessionManager.getRecordingCount(roomId);
	}

	public long getPublishingCount(long roomId) {
		return sessionManager.getPublishingCount(roomId);
	}

	public List<Long> getActiveRoomIdsByServer(Server server) {
		return sessionManager.getActiveRoomIdsByServer(server == null ? serverUtil.getCurrentServer() : server);
	}

	public String getSessionStatistics() {
		return sessionManager.getSessionStatistics();
	}

	public void sessionStart() {
		sessionManager.sessionStart();
	}
	
}
