/****************************************************************
 * Copyright (C) 2005 LAMS Foundation (http://lamsfoundation.org)
 * =============================================================
 * License Information: http://lamsfoundation.org/licensing/lams/2.0/
 * 
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2.0 
 * as published by the Free Software Foundation.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
 * USA
 * 
 * http://www.gnu.org/licenses/gpl.txt
 * ****************************************************************
 */

/* $$Id: TwitterLearnerStarterAction.java,v 1.27 2007/02/07 02:42:22 fmalikoff Exp $$ */
package org.lamsfoundation.lams.tool.twitter.web;

import java.util.Date;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.apache.log4j.Logger;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;
import org.apache.struts.action.ActionMessage;
import org.apache.struts.action.ActionMessages;
import org.apache.struts.util.MessageResources;
import org.lamsfoundation.lams.notebook.model.NotebookEntry;
import org.lamsfoundation.lams.notebook.service.CoreNotebookConstants;
import org.lamsfoundation.lams.tool.ToolAccessMode;
import org.lamsfoundation.lams.tool.twitter.TwitterApplicationException;
import org.lamsfoundation.lams.tool.twitter.TwitterConstants;
import org.lamsfoundation.lams.tool.twitter.TwitterContent;
import org.lamsfoundation.lams.tool.twitter.TwitterUser;
import org.lamsfoundation.lams.tool.twitter.TwitterUserTweet;
import org.lamsfoundation.lams.tool.twitter.service.ITwitterService;
import org.lamsfoundation.lams.tool.twitter.service.TwitterServiceProxy;
import org.lamsfoundation.lams.tool.twitter.util.TwitterWebUtil;
import org.lamsfoundation.lams.usermanagement.dto.UserDTO;
import org.lamsfoundation.lams.util.WebUtil;
import org.lamsfoundation.lams.web.action.LamsDispatchAction;
import org.lamsfoundation.lams.web.session.SessionManager;
import org.lamsfoundation.lams.web.util.AttributeNames;

import winterwell.jtwitter.Twitter;
import winterwell.jtwitter.Twitter.User;
//import winterwell.jtwitter.TwitterException;

/**
 * Creation Date: 27-06-05
 * 
 * The learner url can be of three modes learner, teacher or author. Depending on 
 * what mode was set, it will trigger the corresponding action. If the mode parameter
 * is missing or a key is not found in the keymap, it will call the unspecified method
 * which defaults to the learner action. 
 *  
 * <p>The learner action, checks the defineLater and runOffline flags, and if required
 * it will show the learner the message screen indicating a reason why they cant see
 * the contents of the twitter.
 * If none of the flags are set, then the learner is able to see the twitter. 
 * </p>
 * <p>The difference between author mode (which is basically the preview)
 * is that if the defineLater flag is set, it will not be able to see the twitter screen
 * </p>
 * 
 * ----------------XDoclet Tags--------------------
 * 
 * @struts:action path="/starter/learner" name="TwitterLearnerForm" scope="request" type="org.lamsfoundation.lams.tool.twitter.web.TwitterLearnerStarterAction"
 *               validate="false" parameter="mode"
 * @struts:action-forward name="displayLearnerContent" path=".learnerContent"
 * @struts:action-forward name="displayMessage" path=".message"
 * @struts:action-forward name="defineLater" path=".defineLater"
 * @struts:action-forward name="showTwitter" path="/twitter.do?method=show"
 * ----------------XDoclet Tags--------------------
 */

public class TwitterLearnerStarterAction extends LamsDispatchAction {
    
    static Logger logger = Logger.getLogger(TwitterLearnerStarterAction.class.getName());
   
	private UserDTO getUserDTO(HttpServletRequest request) {
    	// set up the user details
    	HttpSession ss = SessionManager.getSession();
		UserDTO user = (UserDTO) ss.getAttribute(AttributeNames.USER);
		if ( user == null )
		{
		    MessageResources resources = getResources(request);
		    String error = resources.getMessage(TwitterConstants.ERR_MISSING_PARAM, "User");
		    logger.error(error);
			throw new TwitterApplicationException(error);
		}
		return user;
    }
    
    /** Get the user id from the shared session */
	public Long getUserID(HttpServletRequest request) {
		UserDTO user = getUserDTO(request);
        return new Long(user.getUserID().longValue());
	}

    /** Get the user id from the url - needed for the monitoring mode */
	public Long getUserIDFromURLCall(HttpServletRequest request) {
		return WebUtil.readLongParam(request, AttributeNames.PARAM_USER_ID, false);
    }

    public ActionForward unspecified(
    		ActionMapping mapping,
    		ActionForm form,
    		HttpServletRequest request,
    		HttpServletResponse response)
    {
        
        return learner(mapping, form, request, response);
    }
   
    public ActionForward learner(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws TwitterApplicationException {

	HttpSession session = request.getSession(true);
	
	TwitterContent twitterContent = null;
	TwitterUser twitterUser = null;
	saveMessages(request, null);

	TwitterLearnerForm learnerForm = (TwitterLearnerForm)form;
	learnerForm.setTweet("");

	ActionMessages message = new ActionMessages();
	ITwitterService twitterService = TwitterServiceProxy.getTwitterService(getServlet().getServletContext());

	Long toolSessionID = TwitterWebUtil.convertToLong(learnerForm.getToolSessionID());

	if (toolSessionID == null)
	{
	    String error = "Unable to continue. The parameters tool session id is missing";
	    logger.error(error);
	    throw new TwitterApplicationException(error);
	}

	twitterContent = twitterService.retrieveTwitterBySessionID(toolSessionID);	

	if(twitterContent == null)
	{
	    String error = "An Internal error has occurred. Please exit and retry this sequence";
	    logger.error(error);				
	    throw new TwitterApplicationException(error);
	}  

	if ( isFlagSet(twitterContent, TwitterConstants.FLAG_DEFINE_LATER) ) {
	    return mapping.findForward(TwitterConstants.DEFINE_LATER);
	}

	boolean readOnly = false;
	ToolAccessMode mode = WebUtil.readToolAccessModeParam(request, AttributeNames.PARAM_MODE,false);
	    
	    
	if(!(session.getAttribute("twitterUsername") != null && session.getAttribute("twitterPassword") != null)){
	    return mapping.findForward("showTwitter");
	}
	    
	
	Long userID = null;
	if (mode == ToolAccessMode.LEARNER || mode == ToolAccessMode.AUTHOR )
	{
	    userID = getUserID(request);
	    twitterUser = twitterService.retrieveTwitterUserBySession(userID, toolSessionID);

	    if ( ! twitterContent.isContentInUse() ) {
		/* Set the ContentInUse flag to true, and defineLater flag to false */
		twitterContent.setContentInUse(true);
		twitterService.saveTwitter(twitterContent);
	    }

	    if (twitterUser == null)
	    {
		//create a new user with this session id
		twitterUser = new TwitterUser(userID);
		UserDTO user = getUserDTO(request);
		twitterUser.setUsername(user.getLogin());
		twitterUser.setFullname(user.getFirstName()+" "+user.getLastName());
		twitterService.addUser(toolSessionID, twitterUser);        	
	    }
	} 
	else{
	    //user will not exist if force completed.
	    userID = getUserIDFromURLCall(request);
	    twitterUser = twitterService.retrieveTwitterUserBySession(userID, toolSessionID);
	    readOnly = true;

	}

	TwitterUserTweet[] userTweets;
	int currentTweets = twitterService.retrieveNumberOfTweetsByUser(userID, twitterContent.getUid());
	
	learnerForm.setContentID(twitterContent.getUid().toString());
	learnerForm.setUserID(twitterUser.getUid().toString());
	learnerForm.setTwitterUsername(session.getAttribute("twitterUsername").toString());
	
	if(request.getAttribute("tweetMode") == "user"){
	    userTweets = twitterService.retrieveTwitterUserTweetByUser(userID, twitterContent.getUid());
	}
	else{
	    userTweets = twitterService.retrieveTwitterUserTweet(twitterContent.getUid());
	}
	
	learnerForm.copyValuesIntoForm(twitterContent, readOnly, mode.toString(), userTweets, currentTweets);

	NotebookEntry notebookEntry = twitterService.getEntry(toolSessionID, CoreNotebookConstants.NOTEBOOK_TOOL, TwitterConstants.TOOL_SIGNATURE, userID.intValue());
	if (notebookEntry != null) {
	    request.setAttribute("reflectEntry", notebookEntry.getEntry());
	}
	request.setAttribute("reflectInstructions", twitterContent.getReflectInstructions());
	request.setAttribute("reflectOnActivity", twitterContent.getReflectOnActivity());
	
	Boolean userFinished = (twitterUser!=null && TwitterUser.COMPLETED.equals(twitterUser.getUserStatus()));
	request.setAttribute("userFinished", userFinished);

	/*
	*Checks to see if the runOffline flag is set.
	*If the particular flag is set, control is forwarded to jsp page
	*displaying to the user the message according to what flag is set.
	*/
	if (displayMessageToUser(twitterContent, message))
	{
	    saveMessages(request, message);
	    return mapping.findForward(TwitterConstants.DISPLAY_MESSAGE);
	}

	return mapping.findForward(TwitterConstants.DISPLAY_LEARNER_CONTENT);

    }
    
    public ActionForward teacher(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws TwitterApplicationException {
        return learner(mapping, form, request, response);
    }
    
    public ActionForward author(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws TwitterApplicationException {
        
    	return learner(mapping, form, request, response);

    }
    

    
    
    
    /**
     * <p>Performs a check on the flag indicated by <code>flag</code>
     * In this twitter tool, there are 3 possible flags:
     * <li>defineLater</li>
     * <li>contentInUse</li>
     * <li>runOffline</li>
     * <br>Returns true if the flag is set, false otherwise <p>
     * 
     * @param content The instance of TwitterContent
     * @param flag The flag to check, can take the following set of values (defineLater, contentInUse, runOffline)
     * @return Returns true if flag is set, false otherwise
     */
	private boolean isFlagSet(TwitterContent content, int flag) throws TwitterApplicationException
	{
	    switch (flag)
	    {
	    	case TwitterConstants.FLAG_DEFINE_LATER:
	    	    return (content.isDefineLater());
	    	  //  break;
	    	case TwitterConstants.FLAG_CONTENT_IN_USE:
	    		return (content.isContentInUse());
	    	//	break;
	    	case TwitterConstants.FLAG_RUN_OFFLINE:
	    		return(content.isForceOffline()); 
	    //		break;
	    	default:
	    	    throw new TwitterApplicationException("Invalid flag");
	    }
	}
	
	/**
	 * <p> This methods checks the defineLater and runOffline flag. 
	 * If defineLater flag is set, then a message is added to an ActionMessages
	 * object saying that the contents have not been defined yet. If the runOffline 
	 * flag is set, a message is added to ActionMessages saying that the contents
	 * are not being run online. 
	 * This method will return true if any one of the defineLater or runOffline flag is set.
	 * Otherwise false will be returned. </p>
	 * 
	 * @param content The instance of TwitterContent
	 * @param message the instance of ActtionMessages
	 * @return true if any of the flags are set, false otherwise
	 */
	private boolean displayMessageToUser(TwitterContent content, ActionMessages message){
	    boolean isDefineLaterSet = isFlagSet(content, TwitterConstants.FLAG_DEFINE_LATER);
	    boolean isRunOfflineSet = isFlagSet(content, TwitterConstants.FLAG_RUN_OFFLINE);
	    if(isDefineLaterSet || isRunOfflineSet)
	    {
		if (isDefineLaterSet)
		{
		    message.add(ActionMessages.GLOBAL_MESSAGE, new ActionMessage("message.defineLaterSet"));
		}
		if (isRunOfflineSet)
		{
		    message.add(ActionMessages.GLOBAL_MESSAGE, new ActionMessage("message.runOfflineSet"));
		}
		return true;
	    }
	    else
		return false;
	}
 }
