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

import java.io.File;
import java.io.FilenameFilter;
import java.util.Arrays;
import java.util.Comparator;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.Map;

import org.apache.commons.collections.ComparatorUtils;
import org.apache.openmeetings.data.whiteboard.WhiteBoardObjectListManagerById;
import org.apache.openmeetings.data.whiteboard.WhiteBoardObjectSyncManager;
import org.apache.openmeetings.db.dao.server.ISessionManager;
import org.apache.openmeetings.db.dao.server.SessiondataDao;
import org.apache.openmeetings.db.dao.user.UserDao;
import org.apache.openmeetings.db.dto.room.Cliparts;
import org.apache.openmeetings.db.dto.room.WhiteboardObject;
import org.apache.openmeetings.db.dto.room.WhiteboardObjectList;
import org.apache.openmeetings.db.dto.room.WhiteboardSyncLockObject;
import org.apache.openmeetings.db.entity.room.Client;
import org.apache.openmeetings.remote.red5.ScopeApplicationAdapter;
import org.apache.openmeetings.util.AuthLevelUtil;
import org.apache.openmeetings.util.OmFileHelper;
import org.red5.logging.Red5LoggerFactory;
import org.red5.server.api.IConnection;
import org.red5.server.api.Red5;
import org.red5.server.api.scope.IScope;
import org.red5.server.api.service.IPendingServiceCall;
import org.red5.server.api.service.IPendingServiceCallback;
import org.slf4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;

/**
 * 
 * @author sebastianwagner
 * 
 */
public class WhiteBoardService implements IPendingServiceCallback {

	private static final Logger log = Red5LoggerFactory.getLogger(
			WhiteBoardService.class, "openmeetings");
	@Autowired
	private UserDao userDao;
	@Autowired
	private final ScopeApplicationAdapter scopeApplicationAdapter = null;
	@Autowired
	private final ISessionManager sessionManager = null;
	@Autowired
	private final WhiteBoardObjectSyncManager whiteBoardObjectListManager = null;
	@Autowired
	private final WhiteBoardObjectListManagerById whiteBoardObjectListManagerById = null;
	@Autowired
	private SessiondataDao sessiondataDao;

	public Long getNewWhiteboardId() {
		try {

			IConnection current = Red5.getConnectionLocal();
			String streamid = current.getClient().getId();
			Client currentClient = this.sessionManager
					.getClientByStreamId(streamid, null);
			Long room_id = currentClient.getRoom_id();

			Long whiteBoardId = this.whiteBoardObjectListManagerById
					.getNewWhiteboardId(room_id);

			return whiteBoardId;

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

	public Boolean deleteWhiteboard(Long whiteBoardId) {
		try {
			IConnection current = Red5.getConnectionLocal();
			String streamid = current.getClient().getId();
			Client currentClient = this.sessionManager
					.getClientByStreamId(streamid, null);
			Long room_id = currentClient.getRoom_id();

			WhiteboardObjectList whiteboardObjectList = this.whiteBoardObjectListManagerById
					.getWhiteBoardObjectListByRoomId(room_id);

			for (Iterator<Long> iter = whiteboardObjectList
					.getWhiteboardObjects().keySet().iterator(); iter.hasNext();) {
				Long storedWhiteboardId = iter.next();

				log.debug(" :: storedWhiteboardId :: " + storedWhiteboardId);

				if (storedWhiteboardId.equals(whiteBoardId)) {
					log.debug("Found Whiteboard to Remove");
				}
			}
			Object returnValue = whiteboardObjectList.getWhiteboardObjects()
					.remove(whiteBoardId);

			log.debug(" :: whiteBoardId :: " + whiteBoardId);

			this.whiteBoardObjectListManagerById
					.setWhiteBoardObjectListRoomObj(room_id,
							whiteboardObjectList);

			if (returnValue != null) {
				return true;
			} else {
				return false;
			}

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

	public WhiteboardObjectList getRoomItemsBy() {
		try {
			IConnection current = Red5.getConnectionLocal();
			String streamid = current.getClient().getId();
			Client currentClient = this.sessionManager
					.getClientByStreamId(streamid, null);
			Long room_id = currentClient.getRoom_id();

			log.debug("getRoomItems: " + room_id);
			WhiteboardObjectList whiteboardObjectList = this.whiteBoardObjectListManagerById
					.getWhiteBoardObjectListByRoomId(room_id);

			if (whiteboardObjectList.getWhiteboardObjects().size() == 0) {

				Long whiteBoardId = this.whiteBoardObjectListManagerById
						.getNewWhiteboardId(room_id);

				this.whiteBoardObjectListManagerById
						.setWhiteBoardObjectListRoomObjAndWhiteboardId(room_id,
								new WhiteboardObject(), whiteBoardId);

				log.debug("Init New Room List");

				whiteboardObjectList = this.whiteBoardObjectListManagerById
						.getWhiteBoardObjectListByRoomId(room_id);

				return whiteboardObjectList;

			} else {

				return whiteboardObjectList;

			}

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

	/**
	 * change the draw status of a user, allow disallow him to draw anybody
	 * besides the Moderator to draw on the whiteboard, only a Moderator is
	 * allowed to trigger this function
	 * 
	 * @param SID
	 * @param publicSID
	 * @param canDraw
	 * @return null in case of success, false otherwise
	 */
	public Boolean setCanDraw(String SID, String publicSID, boolean canDraw) {
		try {

			IConnection current = Red5.getConnectionLocal();
			String streamid = current.getClient().getId();
			Client currentClient = this.sessionManager
					.getClientByStreamId(streamid, null);

			Long users_id = sessiondataDao.checkSession(SID);

			if (AuthLevelUtil.hasUserLevel(userDao.getRights(users_id))) {

				if (currentClient.getIsMod()) {
					Client rcl = this.sessionManager
							.getClientByPublicSID(publicSID, false, null);

					if (rcl != null) {
						rcl.setCanDraw(canDraw);
						this.sessionManager.updateClientByStreamId(
								rcl.getStreamid(), rcl, false, null);

						HashMap<Integer, Object> newMessage = new HashMap<Integer, Object>();
						newMessage.put(0, "updateDrawStatus");
						newMessage.put(1, rcl);
						this.scopeApplicationAdapter
								.sendMessageWithClientWithSyncObject(newMessage, true);

					} else {
						return false;
					}
				} else {
					return false;
				}
			}

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

	public Boolean setCanShare(String SID, String publicSID, boolean canShare) {
		try {

			IConnection current = Red5.getConnectionLocal();
			String streamid = current.getClient().getId();
			Client currentClient = this.sessionManager
					.getClientByStreamId(streamid, null);

			Long users_id = sessiondataDao.checkSession(SID);

			if (AuthLevelUtil.hasUserLevel(userDao.getRights(users_id))) {

				if (currentClient.getIsMod()) {
					Client rcl = this.sessionManager
							.getClientByPublicSID(publicSID, false, null);

					if (rcl != null) {
						rcl.setCanShare(canShare);
						this.sessionManager.updateClientByStreamId(
								rcl.getStreamid(), rcl, false, null);

						HashMap<Integer, Object> newMessage = new HashMap<Integer, Object>();
						newMessage.put(0, "updateDrawStatus");
						newMessage.put(1, rcl);
						this.scopeApplicationAdapter
								.sendMessageWithClientWithSyncObject(newMessage, true);

					} else {
						return false;
					}
				} else {
					return false;
				}
			}

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

	public Boolean setCanRemote(String SID, String publicSID, boolean canRemote) {
		try {

			IConnection current = Red5.getConnectionLocal();
			String streamid = current.getClient().getId();
			Client currentClient = this.sessionManager
					.getClientByStreamId(streamid, null);

			Long users_id = sessiondataDao.checkSession(SID);

			if (AuthLevelUtil.hasUserLevel(userDao.getRights(users_id))) {

				if (currentClient.getIsMod()) {
					Client rcl = this.sessionManager
							.getClientByPublicSID(publicSID, false, null);

					if (rcl != null) {
						rcl.setCanRemote(canRemote);
						this.sessionManager.updateClientByStreamId(
								rcl.getStreamid(), rcl, false, null);

						HashMap<Integer, Object> newMessage = new HashMap<Integer, Object>();
						newMessage.put(0, "updateDrawStatus");
						newMessage.put(1, rcl);
						this.scopeApplicationAdapter
								.sendMessageWithClientWithSyncObject(newMessage, true);

					} else {
						return false;
					}
				} else {
					return false;
				}
			}

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

    public Boolean setCanGiveAudio(String SID, String publicSID, boolean canGiveAudio) {
		try {
            log.debug("[setCanGiveAudio] " + SID + ", " + publicSID + ", " + canGiveAudio);
			IConnection current = Red5.getConnectionLocal();
			String streamid = current.getClient().getId();
			Client currentClient = this.sessionManager
					.getClientByStreamId(streamid, null);

			Long users_id = sessiondataDao.checkSession(SID);

			if (AuthLevelUtil.hasUserLevel(userDao.getRights(users_id))) {
				if (currentClient.getIsMod()) {
					Client rcl = this.sessionManager
							.getClientByPublicSID(publicSID, false, null);

					if (rcl != null) {
						rcl.setCanGiveAudio(canGiveAudio);
				        this.sessionManager.updateClientByStreamId(
				                rcl.getStreamid(), rcl, false, null);

				        HashMap<Integer, Object> newMessage = new HashMap<Integer, Object>();
				        newMessage.put(0, "updateGiveAudioStatus");
				        newMessage.put(1, rcl);
				        this.scopeApplicationAdapter
				                .sendMessageWithClientWithSyncObject(newMessage, true);
					} else {
						return false;
					}
				} else {
					return false;
				}
			}

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

	public WhiteboardSyncLockObject startNewSyncprocess() {
		try {

			IConnection current = Red5.getConnectionLocal();
			String streamid = current.getClient().getId();
			Client currentClient = this.sessionManager
					.getClientByStreamId(streamid, null);
			Long room_id = currentClient.getRoom_id();

			WhiteboardSyncLockObject wSyncLockObject = new WhiteboardSyncLockObject();
			wSyncLockObject.setAddtime(new Date());
			wSyncLockObject.setPublicSID(currentClient.getPublicSID());
			wSyncLockObject.setInitialLoaded(true);

			Map<String, WhiteboardSyncLockObject> syncListRoom = this.whiteBoardObjectListManager
					.getWhiteBoardSyncListByRoomid(room_id);

			wSyncLockObject.setCurrentLoadingItem(true);
			wSyncLockObject.setStarttime(new Date());

			syncListRoom.put(currentClient.getPublicSID(), wSyncLockObject);
			this.whiteBoardObjectListManager.setWhiteBoardSyncListByRoomid(
					room_id, syncListRoom);
			
			//Sync to clients
			this.scopeApplicationAdapter.sendMessageToCurrentScope("sendSyncFlag", wSyncLockObject, true);

			return wSyncLockObject;

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

	public void sendCompletedSyncEvent() {
		try {

			IConnection current = Red5.getConnectionLocal();
			String streamid = current.getClient().getId();
			Client currentClient = this.sessionManager
					.getClientByStreamId(streamid, null);
			Long room_id = currentClient.getRoom_id();

			Map<String, WhiteboardSyncLockObject> syncListRoom = this.whiteBoardObjectListManager
					.getWhiteBoardSyncListByRoomid(room_id);

			WhiteboardSyncLockObject wSyncLockObject = syncListRoom
					.get(currentClient.getPublicSID());

			if (wSyncLockObject == null) {
				log.error("WhiteboardSyncLockObject not found for this Client "
						+ syncListRoom);
				return;
			} else if (!wSyncLockObject.isCurrentLoadingItem()) {
				log.warn("WhiteboardSyncLockObject was not started yet "
						+ syncListRoom);
				return;
			} else {
				syncListRoom.remove(currentClient.getPublicSID());
				this.whiteBoardObjectListManager.setWhiteBoardSyncListByRoomid(
						room_id, syncListRoom);

				int numberOfInitial = this
						.getNumberOfInitialLoaders(syncListRoom);

				if (numberOfInitial == 0) {
					scopeApplicationAdapter.sendMessageToCurrentScope("sendSyncCompleteFlag", wSyncLockObject, true);
				} else {
					return;
				}
			}

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

	private int getNumberOfInitialLoaders(
			Map<String, WhiteboardSyncLockObject> syncListRoom)
			throws Exception {
		int number = 0;
		for (Iterator<String> iter = syncListRoom.keySet().iterator(); iter
				.hasNext();) {
			WhiteboardSyncLockObject lockObject = syncListRoom.get(iter.next());
			if (lockObject.isInitialLoaded()) {
				number++;
			}
		}
		return number;
	}

	/*
	 * Image Sync Sequence
	 */

	public void startNewObjectSyncProcess(String object_id, boolean isStarting) {
		try {

			log.debug("startNewObjectSyncprocess: " + object_id);

			IConnection current = Red5.getConnectionLocal();
			String streamid = current.getClient().getId();
			Client currentClient = this.sessionManager
					.getClientByStreamId(streamid, null);
			Long room_id = currentClient.getRoom_id();

			WhiteboardSyncLockObject wSyncLockObject = new WhiteboardSyncLockObject();
			wSyncLockObject.setAddtime(new Date());
			wSyncLockObject.setPublicSID(currentClient.getPublicSID());
			wSyncLockObject.setStarttime(new Date());

			Map<String, WhiteboardSyncLockObject> syncListImage = this.whiteBoardObjectListManager
					.getWhiteBoardObjectSyncListByRoomAndObjectId(room_id,
							object_id);
			syncListImage.put(currentClient.getPublicSID(), wSyncLockObject);
			this.whiteBoardObjectListManager
					.setWhiteBoardImagesSyncListByRoomAndObjectId(room_id,
							object_id, syncListImage);

			// Do only send the Token to show the Loading Splash for the
			// initial-Request that starts the loading
			if (isStarting) {
				scopeApplicationAdapter.sendMessageToCurrentScope("sendObjectSyncFlag", wSyncLockObject, true);
			}

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

	public int sendCompletedObjectSyncEvent(String object_id) {
		try {

			log.debug("sendCompletedObjectSyncEvent: " + object_id);

			IConnection current = Red5.getConnectionLocal();
			String streamid = current.getClient().getId();
			Client currentClient = this.sessionManager
					.getClientByStreamId(streamid, null);
			Long room_id = currentClient.getRoom_id();

			Map<String, WhiteboardSyncLockObject> syncListImage = this.whiteBoardObjectListManager
					.getWhiteBoardObjectSyncListByRoomAndObjectId(room_id,
							object_id);

			log.debug("sendCompletedObjectSyncEvent syncListImage: "
					+ syncListImage);

			WhiteboardSyncLockObject wSyncLockObject = syncListImage
					.get(currentClient.getPublicSID());

			if (wSyncLockObject == null) {
				log.error("WhiteboardSyncLockObject not found for this Client "
						+ currentClient.getPublicSID());
				log.error("WhiteboardSyncLockObject not found for this syncListImage "
						+ syncListImage);
				return -2;

			} else {

				log.debug("sendCompletedImagesSyncEvent remove: "
						+ currentClient.getPublicSID());

				syncListImage.remove(currentClient.getPublicSID());
				this.whiteBoardObjectListManager
						.setWhiteBoardImagesSyncListByRoomAndObjectId(room_id,
								object_id, syncListImage);

				int numberOfInitial = this.whiteBoardObjectListManager
						.getWhiteBoardObjectSyncListByRoomid(room_id).size();

				log.debug("sendCompletedImagesSyncEvent numberOfInitial: "
						+ numberOfInitial);

				if (numberOfInitial == 0) {
					scopeApplicationAdapter.sendMessageToCurrentScope("sendObjectSyncCompleteFlag", wSyncLockObject, true);
					return 1;
				} else {
					return -4;
				}
			}

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

	public synchronized void removeUserFromAllLists(IScope scope,
			Client currentClient) {
		try {

			Long room_id = currentClient.getRoom_id();

			// TODO: Maybe we should also check all rooms, independent from the
			// current room_id if there is any user registered
			if (room_id != null) {

				log.debug("removeUserFromAllLists this.whiteBoardObjectListManager: "
						+ this.whiteBoardObjectListManager);
				log.debug("removeUserFromAllLists room_id: " + room_id);

				// Check Initial Loaders
				Map<String, WhiteboardSyncLockObject> syncListRoom = this.whiteBoardObjectListManager
						.getWhiteBoardSyncListByRoomid(room_id);

				WhiteboardSyncLockObject wSyncLockObject = syncListRoom
						.get(currentClient.getPublicSID());

				if (wSyncLockObject != null) {
					syncListRoom.remove(currentClient.getPublicSID());
				}
				this.whiteBoardObjectListManager.setWhiteBoardSyncListByRoomid(
						room_id, syncListRoom);

				int numberOfInitial = this
						.getNumberOfInitialLoaders(syncListRoom);

				log.debug("scope " + scope);

				if (numberOfInitial == 0 && scope != null) {
					
					scopeApplicationAdapter.sendMessageToCurrentScope("sendSyncCompleteFlag", wSyncLockObject, false);
					
				}

				// Check Image Loaders
				Map<String, Map<String, WhiteboardSyncLockObject>> syncListRoomImages = this.whiteBoardObjectListManager
						.getWhiteBoardObjectSyncListByRoomid(room_id);

				for (Iterator<String> iter = syncListRoomImages.keySet()
						.iterator(); iter.hasNext();) {
					String object_id = iter.next();
					Map<String, WhiteboardSyncLockObject> syncListImages = syncListRoomImages
							.get(object_id);
					WhiteboardSyncLockObject wImagesSyncLockObject = syncListImages
							.get(currentClient.getPublicSID());
					if (wImagesSyncLockObject != null) {
						syncListImages.remove(currentClient.getPublicSID());
					}
					this.whiteBoardObjectListManager
							.setWhiteBoardImagesSyncListByRoomAndObjectId(
									room_id, object_id, syncListImages);
				}

				int numberOfImageLoaders = this.whiteBoardObjectListManager
						.getWhiteBoardObjectSyncListByRoomid(room_id).size();

				if (numberOfImageLoaders == 0 && scope != null) {
					scopeApplicationAdapter.sendMessageToCurrentScope("sendImagesSyncCompleteFlag", new Object[] { "remove" }, true);
				}

			}

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

	public Cliparts getClipArtIcons() {
		try {
			File clipart_dir = OmFileHelper.getPublicClipartsDir();

			FilenameFilter getFilesOnly = new FilenameFilter() {
				public boolean accept(File b, String name) {
					File f = new File(b, name);
					return !f.isDirectory();
				}
			};

			FilenameFilter getDirectoriesOnly = new FilenameFilter() {
				public boolean accept(File b, String name) {
					File f = new File(b, name);
					return f.isDirectory() && !f.getName().equals("thumb");
				}
			};

			Cliparts cl = new Cliparts();
			cl.setFolderName("general");

			String[] files_general = clipart_dir.list(getFilesOnly);
			@SuppressWarnings("unchecked")
			Comparator<String> comparator = ComparatorUtils.naturalComparator();
			Arrays.sort(files_general, comparator);

			cl.setGeneralList(files_general);
			cl.setSubCategories(new LinkedList<Cliparts>());

			for (File dir : clipart_dir.listFiles(getDirectoriesOnly)) {
				Cliparts cl_sub = new Cliparts();
				cl_sub.setFolderName("math");
				String[] files = dir.list(getFilesOnly);
				Arrays.sort(files, comparator);
				cl_sub.setGeneralList(files);
				cl.getSubCategories().add(cl_sub);
			}

			return cl;

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

	public void resultReceived(IPendingServiceCall arg0) {
		log.debug("resultReceived: " + arg0);
	}
}
