/*
 * The contents of this file are subject to the Mozilla Public License Version 1.1
 * (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.mozilla.org/MPL/>.
 * 
 * Software distributed under the License is distributed on an "AS IS" basis, WITHOUT
 * WARRANTY OF ANY KIND, either express or implied. See the License for the specific
 * language governing rights and limitations under the License.
 * 
 * The Original Code is the Venice Web Communities System.
 * 
 * The Initial Developer of the Original Code is Eric J. Bowersox <erbo@silcom.com>,
 * for Silverwrist Design Studios.  Portions created by Eric J. Bowersox are
 * Copyright (C) 2001 Eric J. Bowersox/Silverwrist Design Studios.  All Rights Reserved.
 * 
 * Contributor(s): 
 */
package com.silverwrist.venice.servlets;

import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
import org.apache.log4j.*;
import com.silverwrist.venice.core.*;
import com.silverwrist.venice.except.*;
import com.silverwrist.venice.servlets.format.*;

public class CommunityOperations extends VeniceServlet
{
  /*--------------------------------------------------------------------------------
   * Static data members
   *--------------------------------------------------------------------------------
   */

  private static final String UNJOIN_CONFIRM_ATTR = "servlets.CommunityOperations.unjoin.confirm";
  private static final String UNJOIN_CONFIRM_PARAM = "confirm";

  private static Category logger = Category.getInstance(CommunityOperations.class);

  /*--------------------------------------------------------------------------------
   * Internal functions
   *--------------------------------------------------------------------------------
   */

  private JoinKeyDialog makeJoinKeyDialog()
  {
    final String desired_name = "JoinKeyDialog";
    DialogCache cache = DialogCache.getDialogCache(getServletContext());

    if (!(cache.isCached(desired_name)))
    { // create a template and save it off
      JoinKeyDialog template = new JoinKeyDialog();
      cache.saveTemplate(template);

    } // end if

    // return a new copy
    return (JoinKeyDialog)(cache.getNewDialog(desired_name));

  } // end makeJoinKeyDialog

  private CreateCommunityDialog makeCreateCommunityDialog() throws ServletException
  {
    final String desired_name = "CreateCommunityDialog";
    DialogCache cache = DialogCache.getDialogCache(getServletContext());

    if (!(cache.isCached(desired_name)))
    { // create a template and save it off
      CreateCommunityDialog template = new CreateCommunityDialog();
      cache.saveTemplate(template);

    } // end if

    // return a new copy
    return (CreateCommunityDialog)(cache.getNewDialog(desired_name));

  } // end makeCreateCommunityDialog

  /*--------------------------------------------------------------------------------
   * Overrides from class HttpServlet
   *--------------------------------------------------------------------------------
   */

  public String getServletInfo()
  {
    String rc = "CommunityOperations servlet - General community operations (join, unjoin, etc.)\n"
              + "Part of the Venice Web Communities System\n";
    return rc;

  } // end getServletInfo

  /*--------------------------------------------------------------------------------
   * Overrides from class VeniceServlet
   *--------------------------------------------------------------------------------
   */

  protected VeniceContent doVeniceGet(HttpServletRequest request, VeniceEngine engine,
				      UserContext user, RenderData rdat)
    throws ServletException, IOException, VeniceServletResult
  {
    // get the command we want to use
    String cmd = getStandardCommandParam(request);
    setMyLocation(request,"sigops?" + request.getQueryString());

    if (cmd.equals("J"))
    { // "J" = "Join" (requires community parameter)
      CommunityContext comm = getCommunityParameter(request,user,true,"top");

      if (!(comm.canJoin()))  // not permitted to join!
	return new ErrorBox("Community Error","You are not permitted to join this community.","top");

      if (comm.isPublicCommunity())
      { // attempt to join right now!  (no join key required)
	try
	{ // call down to join the community
	  comm.join(null);

	  // success! display the "welcome" page
	  clearMenu(request);  // force the clear to regen the menus
	  changeMenuCommunity(request,comm);
	  return new CommunityWelcome(comm);
	  
	} // end try
	catch (AccessError ae)
	{ // access error
	  return new ErrorBox("Access Error","Unable to join community: " + ae.getMessage(),"top");

	} // end catch
	catch (DataException de)
	{ // data exception doing something
	  return new ErrorBox("Database Error","Database error joining community: " + de.getMessage(),"top");

	} // end catch

      } // end if (public community)
      else
      { // we need to prompt them for the join key....
	JoinKeyDialog dlg = makeJoinKeyDialog();
	dlg.setupDialog(comm);
	changeMenuCommunity(request,comm);
	return dlg;

      } // end else (private community)

    } // end if ("J" command)

    if (cmd.equals("U"))
    { // "U" = "Unjoin (requires community parameter)
      CommunityContext comm = getCommunityParameter(request,user,true,"top");

      if (!(comm.canUnjoin()))
	return new ErrorBox("Community Error","You cannot unjoin this community.","top");
      
      // OK, let's test for a confirmation...
      if (ConfirmBox.isConfirmed(request,UNJOIN_CONFIRM_ATTR,UNJOIN_CONFIRM_PARAM))
      { // OK, if you say so, let's unjoin!
	try
	{ // do the unjoin now...
	  comm.unjoin();

	} // end try
	catch (AccessError ae)
	{ // access error
	  return new ErrorBox("Access Error","Unable to unjoin community: " + ae.getMessage(),"top");

	} // end catch
	catch (DataException de)
	{ // data exception doing something
	  return new ErrorBox("Database Error","Database error unjoining community: " + de.getMessage(),"top");

	} // end catch

	// after which, redirect back to the top
	clearMenu(request);
	throw new RedirectResult("top");

      } // end if
      else
      { // not a proper confirmation - display the confirm box
	String message = "Are you sure you want to unjoin the '" + comm.getName() + "' community?";
	return new ConfirmBox(request,UNJOIN_CONFIRM_ATTR,UNJOIN_CONFIRM_PARAM,"Unjoining community",
			      message,"sigops?cmd=U&sig=" + comm.getCommunityID(),"sig/" + comm.getAlias());

      } // end else

    } // end if ("U" command)

    if (cmd.equals("C"))
    { // "C" - Create community (no parameters)
      if (!(user.canCreateCommunity()))
	return new ErrorBox("Community Error","You are not permitted to create communities.","top");

      // present the "Create New Community" dialog
      CreateCommunityDialog dlg = makeCreateCommunityDialog();
      dlg.setupDialog(engine);
      dlg.setFieldValue("language","en-US");
      dlg.setFieldValue("country","US");
      changeMenuTop(request);
      return dlg;

    } // end if ("C" command)

    if (cmd.equals("I"))
    { // "I" - Send Invitation (requires community parameter)
      CommunityContext comm = getCommunityParameter(request,user,true,"top");

      if (!(comm.canSendInvitation()))
	return new ErrorBox("Community Error","You are not permitted to send an invitation.",
			    "sig/" + comm.getAlias());

      // present the "Invitation" dialog
      return new Invitation(comm);

    } // end if ("I" command)

    if (cmd.equals("M"))
    { // "M" = List Members
      CommunityContext comm = getCommunityParameter(request,user,true,"top");
      if (logger.isDebugEnabled())
	logger.debug("Member list for community: " + comm.getName());

      try
      { // return the view dialog
	ViewCommunityMembers view = new ViewCommunityMembers(engine,comm);
	view.doInitialList();
	changeMenuCommunity(request,comm);
	return view;

      } // end try
      catch (DataException de)
      { // unable to get community members list
	return new ErrorBox("Database Error","Database error getting community members list: "
			                     + de.getMessage(),"top");

      } // end catch

    } // end if ("M" command)

    // this is an error!
    logger.error("invalid command to CommunityOperations.doGet: " + cmd);
    return new ErrorBox("Internal Error","Invalid command to CommunityOperations.doGet","top");

  } // end doVeniceGet

  protected VeniceContent doVenicePost(HttpServletRequest request, VeniceEngine engine,
				       UserContext user, RenderData rdat)
    throws ServletException, IOException, VeniceServletResult
  {
    // get the command we want to use
    String cmd = getStandardCommandParam(request);
    setMyLocation(request,"sigops?cmd=" + cmd);

    if (cmd.equals("J"))
    { // "J" = Join Community (requires community parameter)
      CommunityContext comm = getCommunityParameter(request,user,true,"top");
      setMyLocation(request,"sigops?cmd=J&sig=" + comm.getCommunityID());
      JoinKeyDialog dlg = makeJoinKeyDialog();

      if (dlg.isButtonClicked(request,"cancel")) // cancel - go back to community opening page
	throw new RedirectResult("sig/" + comm.getAlias());

      if (!(comm.canJoin()))  // not permitted to join!
	return new ErrorBox("Community Error","You are not permitted to join this community.","top");

      if (dlg.isButtonClicked(request,"join"))
      { // OK, go join the community
	dlg.loadValues(request);  // load the dialog

	try
	{ // attempt to join the community!
	  dlg.doDialog(comm);

	  // success! display the "welcome" page
	  clearMenu(request);  // force the clear to regen the menus
	  changeMenuCommunity(request,comm);
	  return new CommunityWelcome(comm);

	} // end try
	catch (ValidationException ve)
	{ // here, a validation exception causes us to recycle and retry
	  dlg.resetOnError(ve.getMessage() + " Please try again.");
	  changeMenuCommunity(request,comm);
	    
	} // end catch
	catch (AccessError ae)
	{ // this is probably a bogus key - let them retry
	  dlg.resetOnError(ae.getMessage() + " Please try again.");
	  changeMenuCommunity(request,comm);
	    
	} // end catch
	catch (DataException de)
	{ // database error joining something
	  return new ErrorBox("Database Error","Database error joining community: " + de.getMessage(),"top");

	} // end catch

	return dlg;  // recycle and try aagin

      } // end if ("join" clicked)

      // error - don't know what button was clicked
      logger.error("no known button click on CommunityOperations.doPost, cmd=J");
      return new ErrorBox("Internal Error","Unknown command button pressed","top");

    } // end if ("J" command)

    if (cmd.equals("C"))
    { // "C" = Create New Community
      if (!(user.canCreateCommunity()))
	return new ErrorBox("Community Error","You are not permitted to create communities.","top");

      // load the "Create Communities" dialog
      CreateCommunityDialog dlg = makeCreateCommunityDialog();
      dlg.setupDialog(engine);

      if (dlg.isButtonClicked(request,"cancel")) // cancel - go back to top
	throw new RedirectResult("top");

      if (dlg.isButtonClicked(request,"create"))
      { // OK, they actually want to create the new community...
	dlg.loadValues(request);  // load the form data

	try
	{ // attempt to create the community!
	  CommunityContext comm = dlg.doDialog(user);

	  // created successfully - display a "new community welcome" page
	  changeMenuCommunity(request,comm);  // display menus for the first time!
	  return new NewCommunityWelcome(comm);

	} // end try
	catch (ValidationException ve)
	{ // here, a validation exception causes us to recycle and retry
	  dlg.resetOnError(ve.getMessage() + " Please try again.");
	  changeMenuTop(request);
	    
	} // end catch
	catch (AccessError ae)
	{ // this is probably a bogus key - let them retry
	  dlg.resetOnError(ae.getMessage() + " Please try again.");
	  changeMenuTop(request);
	    
	} // end catch
	catch (DataException de)
	{ // database error doing something
	  return new ErrorBox("Database Error","Database error creating community: " + de.getMessage(),"top");

	} // end catch

	return dlg;  // put the dialog back up

      } // end if ("create" pressed)

      // error - don't know what button was clicked
      logger.error("no known button click on CommunityOperations.doPost, cmd=C");
      return new ErrorBox("Internal Error","Unknown command button pressed","top");

    } // end if ("C" command)

    if (cmd.equals("I"))
    { // "I" = Send invitation (requires community parameter)
      CommunityContext comm = getCommunityParameter(request,user,true,"top");
      setMyLocation(request,"sigops?cmd=I&sig=" + comm.getCommunityID());
      String on_error = "sig/" + comm.getAlias();

      if (isImageButtonClicked(request,"cancel")) // cancel - go back to community opening page
	throw new RedirectResult(on_error);

      if (isImageButtonClicked(request,"send"))
      { // the "send" button was pressed
	try
	{ // send out the invitation
	  comm.sendInvitation(request.getParameter("addr"),request.getParameter("pb"));

	} // end try
	catch (AccessError ae)
	{ // access error - display error box
	  return new ErrorBox("Access Error",ae.getMessage(),on_error);
	    
	} // end catch
	catch (DataException de)
	{ // database error doing something
	  return new ErrorBox("Database Error","Database error sending invitation: " + de.getMessage(),
			      on_error);

	} // end catch
	catch (EmailException ee)
	{ // error sending the email message
	  return new ErrorBox("E-Mail Error","Error sending e-mail: " + ee.getMessage(),on_error);
	    
	} // end catch

	// all sent - go back to community profile display
	throw new RedirectResult(on_error);
	
      } // end if ("send" pressed)

      // error - don't know what button was clicked
      logger.error("no known button click on CommunityOperations.doPost, cmd=I");
      return new ErrorBox("Internal Error","Unknown command button pressed",on_error);

    } // end if ("I" command)

    if (cmd.equals("M"))
    { // "M" = Display Members List
      CommunityContext comm = getCommunityParameter(request,user,true,"top");
      setMyLocation(request,"sigops?cmd=M&sig=" + comm.getCommunityID());
      String on_error = "sig/" + comm.getAlias();
      if (logger.isDebugEnabled())
	logger.debug("Member list for community: " + comm.getName());

      try
      { // generate the members list
	ViewCommunityMembers view = new ViewCommunityMembers(engine,comm);
	view.doSearch(request);
	changeMenuCommunity(request,comm);
	return view;

      } // end try
      catch (ValidationException ve)
      { // validation error - throw it back to the user
	return new ErrorBox(null,ve.getMessage() + " Please try again.",
			    "sigops?cmd=M&sig=" + comm.getCommunityID());

      } // end catch
      catch (DataException de)
      { // unable to get community members list
	return new ErrorBox("Database Error","Database error getting community members list: "
			                     + de.getMessage(),on_error);

      } // end catch

    } // end if ("M" command)

    // this is an error!
    logger.error("invalid command to CommunityOperations.doPost: " + cmd);
    return new ErrorBox("Internal Error","Invalid command to CommunityOperations.doPost","top");

  } // end doVenicePost

} // end class CommunityOperations



