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

import java.util.Date;
import java.util.List;

import org.apache.openmeetings.data.user.UserManager;
import org.apache.openmeetings.db.dao.room.PollDao;
import org.apache.openmeetings.db.dao.server.ISessionManager;
import org.apache.openmeetings.db.dao.user.UserDao;
import org.apache.openmeetings.db.entity.room.Client;
import org.apache.openmeetings.db.entity.room.PollType;
import org.apache.openmeetings.db.entity.room.RoomPoll;
import org.apache.openmeetings.db.entity.room.RoomPollAnswers;
import org.apache.openmeetings.remote.red5.ScopeApplicationAdapter;
import org.apache.openmeetings.util.OpenmeetingsVariables;
import org.red5.logging.Red5LoggerFactory;
import org.red5.server.api.IConnection;
import org.red5.server.api.Red5;
import org.red5.server.api.service.IPendingServiceCall;
import org.red5.server.api.service.IPendingServiceCallback;
import org.slf4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;

/**
 * 
 * @author swagner
 * 
 */
public class PollService implements IPendingServiceCallback {

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

	@Autowired
	private ISessionManager sessionManager;
	@Autowired
	private UserManager userManager;
	@Autowired
	private UserDao userDao;
	@Autowired
	private ScopeApplicationAdapter scopeApplicationAdapter;
	@Autowired
	private PollDao pollManager;

	public String createPoll(String pollName, String pollQuestion, int pollTypeId) {
		String returnValue = "";
		try {
			log.debug("createPoll: " + pollQuestion);

			IConnection currentcon = Red5.getConnectionLocal();
			Client rc = sessionManager.getClientByStreamId(currentcon.getClient().getId(), null);

			log.debug("rc: " + rc.getStreamid() + " " + rc.getUsername() + " " + rc.getIsMod());

			if (rc.getIsMod()) {
				// will move all existing polls to the archive
				pollManager.closePoll(rc.getRoom_id());
				
				sendNotification(currentcon, "newPoll", pollManager.createPoll(rc, pollName, pollQuestion, (long) pollTypeId));
				returnValue = "200";
			} else {
				returnValue = "202";
			}

		} catch (Exception err) {
			returnValue = "203";
			log.error("[createPoll]", err);
		}
		return returnValue;
	}

	public boolean closePoll() {
		try {
			log.debug("closePoll: ");

			IConnection currentcon = Red5.getConnectionLocal();
			Client rc = sessionManager.getClientByStreamId(currentcon
					.getClient().getId(), null);

			log.debug("rc: " + rc.getStreamid() + " " + rc.getUsername() + " "
					+ rc.getIsMod());

			if (rc.getIsMod()) {
				// will move all existing polls to the archive
				return pollManager.closePoll(rc.getRoom_id());
			}

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

	public boolean deletePoll(Long poll_id) {
		try {
			log.debug("closePoll: ");

			IConnection currentcon = Red5.getConnectionLocal();
			Client rc = sessionManager.getClientByStreamId(currentcon
					.getClient().getId(), null);

			log.debug("rc: " + rc.getStreamid() + " " + rc.getUsername() + " "
					+ rc.getIsMod());

			if (rc.getIsMod()) {
				// will move all existing polls to the archive
				return pollManager.deletePoll(poll_id);
			}

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

	public void sendNotification(IConnection current, String clientFunction, RoomPoll poll) throws Exception {
		Client rc = sessionManager.getClientByStreamId(current.getClient().getId(), null);
		final Long roomId = rc.getRoom_id();
		scopeApplicationAdapter.new MessageSender(current, clientFunction, poll) {
			
			@Override
			public boolean filter(IConnection conn) {
				Client rcl = sessionManager.getClientByStreamId(conn.getClient().getId(), null);
				return (rcl.getIsScreenClient() != null && rcl.getIsScreenClient())
						|| rcl.getRoom_id() == null || !rcl.getRoom_id().equals(roomId) || userDao.get(rcl.getUser_id()) == null;
			}
		}.start();
	}

	public List<PollType> getPollTypeList() {
		return pollManager.getPollTypes();
	}

	public int vote(int pollvalue, int pollTypeId) {
		int returnVal = 0;
		try {
			log.debug("PollService::vote: Enter");
			IConnection current = Red5.getConnectionLocal();
			String streamid = current.getClient().getId();
			Client rc = sessionManager.getClientByStreamId(streamid, null);

			if (rc == null) {
				log.error("RoomClient IS NULL for ClientID: "
						+ current.getClient().getId());
				return -1;
			}
			long roomId = rc.getRoom_id();
			if (!pollManager.hasPoll(roomId)) {
				log.error("POLL IS NULL for RoomId: " + rc.getRoom_id());
				return -1;
			}
			
			if(userDao.get(rc.getUser_id())==null){
				log.debug("vote: Invited users can not vote");
				return -1;
			}
			if (pollManager.hasVoted(roomId, rc.getUser_id())) {
				log.debug("hasVoted: true");
				return -1;
			}
			// get Poll
			RoomPoll roomP = pollManager.getPoll(roomId);

			log.debug("vote: " + pollvalue + " " + pollTypeId + " "
					+ roomP.getPollQuestion());

			log.debug("hasVoted: false");
			RoomPollAnswers rpA = new RoomPollAnswers();
			if (roomP.getPollType().getIsNumericAnswer()) {
				log.debug("numeric");
				rpA.setPointList(pollvalue);
			} else {
				log.debug("boolean");
				// Is boolean Question
				rpA.setAnswer(new Boolean(pollvalue == 1));
			}
			rpA.setVotedUser(userDao.get(rc.getUser_id()));
			rpA.setVoteDate(new Date());
			rpA.setRoomPoll(roomP);
			roomP.getRoomPollAnswerList().add(rpA);
			pollManager.updatePoll(roomP);
			return 1;
		} catch (Exception err) {
			log.error("[vote]", err);
		}
		return returnVal;
	}

	public RoomPoll getVotes() {
		return getPoll();
	}

	public RoomPoll getPoll() {
		try {
			IConnection current = Red5.getConnectionLocal();
			Client rc = sessionManager.getClientByStreamId(current.getClient().getId(), null);

			// get Poll
			return pollManager.getPoll(rc.getRoom_id());
		} catch (Exception err) {
			log.error("[getPoll]", err);
		}
		return null;
	}

	public int checkHasVoted() {
		try {
			IConnection current = Red5.getConnectionLocal();
			String streamid = current.getClient().getId();
			Client rc = this.sessionManager
					.getClientByStreamId(streamid, null);

			long roomId = rc.getRoom_id();
			if(userDao.get(rc.getUser_id())==null){
				log.debug("checkHasVoted: Invited users can not vote");
				return -1;
			}
			if (pollManager.hasPoll(roomId)) {
				return pollManager.hasVoted(roomId, rc.getUser_id()) ? -1 : 1;
			} else {
				return -2;
			}
		} catch (Exception err) {
			log.error("[checkHasVoted]", err);
		}
		return 0;
	}

	public List<RoomPoll> getArchivedPollList() {
		try {
			IConnection current = Red5.getConnectionLocal();
			Client rc = this.sessionManager.getClientByStreamId(current
					.getClient().getId(), null);

			// get Poll
			return pollManager.getArchivedPollList(rc.getRoom_id());
		} catch (Exception err) {
			log.error("[getArchivedPollList]", err);
		}
		return null;
	}

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