/*
 * 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.format;

import java.io.*;
import java.util.*;
import javax.servlet.*;
import javax.servlet.http.*;
import com.silverwrist.util.StringUtil;
import com.silverwrist.venice.security.Role;
import com.silverwrist.venice.core.*;
import com.silverwrist.venice.except.*;

public class CommunityMembership implements JSPRender, SearchMode
{
  /*--------------------------------------------------------------------------------
   * Static data members
   *--------------------------------------------------------------------------------
   */

  // Attribute name for request attribute
  protected static final String ATTR_NAME = "com.silverwrist.venice.content.CommunityMembership";

  /*--------------------------------------------------------------------------------
   * Attributes
   *--------------------------------------------------------------------------------
   */

  private VeniceEngine engine;            // reference to the engine
  private CommunityContext comm;          // the community we're in
  private List display_list = null;       // list of members to display
  private boolean comm_members = false;    // is this a list of community members?
  private int field = -1;                 // search field
  private int mode = -1;                  // search mode
  private String term = null;             // search term
  private int offset = 0;                 // search result offset
  private int find_count = -1;            // search results count
  private List role_choices;              // the list of security roles
  private Role role_comm_host;            // the "Community Host" security role

  /*--------------------------------------------------------------------------------
   * Constructors
   *--------------------------------------------------------------------------------
   */

  public CommunityMembership(VeniceEngine engine, CommunityContext comm)
  {
    this.engine = engine;
    this.comm = comm;
    SecurityInfo sinf = comm.getSecurityInfo();
    this.role_choices = sinf.getRoleList("Community.UserLevels");
    this.role_comm_host = sinf.getRole("Community.Host");

  } // end constructor

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

  private static int getParamInt(ServletRequest request, String name, int default_val)
  {
    String str = request.getParameter(name);
    if (str==null)
      return -1;

    try
    { // parse the integer value
      return Integer.parseInt(str);

    } // end try
    catch (NumberFormatException nfe)
    { // in case of conversion error, return default
      return default_val;

    } // end catch

  } // end getParamInt

  private static boolean isImageButtonClicked(ServletRequest request, String name)
  {
    String val = request.getParameter(name + ".x");
    return (val!=null);

  } // end isImageButtonClicked

  /*--------------------------------------------------------------------------------
   * External static functions
   *--------------------------------------------------------------------------------
   */

  public static CommunityMembership retrieve(ServletRequest request)
  {
    return (CommunityMembership)(request.getAttribute(ATTR_NAME));

  } // end retrieve

  /*--------------------------------------------------------------------------------
   * Implementations from interface VeniceContent
   *--------------------------------------------------------------------------------
   */

  public String getPageTitle(RenderData rdat)
  {
    return "Membership in Community " + comm.getName();

  } // end getPageTitle

  public String getPageQID()
  {
    return null;

  } // end getPageQID

  /*--------------------------------------------------------------------------------
   * Implementations from interface JSPRender
   *--------------------------------------------------------------------------------
   */

  public void store(ServletRequest request)
  {
    request.setAttribute(ATTR_NAME,this);

  } // end store

  public String getTargetJSPName()
  {
    return "comm_member.jsp";

  } // end getTargetJSPName

  /*--------------------------------------------------------------------------------
   * External operations
   *--------------------------------------------------------------------------------
   */

  public void doCommunityMemberList() throws DataException
  {
    this.display_list = comm.getMemberList();
    this.comm_members = true;
    this.term = "";

  } // end doCommunityMemberList

  public void doSearch(ServletRequest request) throws ValidationException, DataException, AccessError
  {
    // Validate the search field parameter.
    field = getParamInt(request,"field",FIELD_USER_NAME);
    if (   (field!=FIELD_USER_NAME) && (field!=FIELD_USER_DESCRIPTION) && (field!=FIELD_USER_GIVEN_NAME)
	   && (field!=FIELD_USER_FAMILY_NAME))
      throw new ValidationException("The field search parameter is not valid.");

    // Validate the search mode parameter.
    mode = getParamInt(request,"mode",SEARCH_PREFIX);
    if ((mode!=SEARCH_PREFIX) && (mode!=SEARCH_SUBSTRING) && (mode!=SEARCH_REGEXP))
      throw new ValidationException("The search mode parameter is not valid.");

    // Retrieve the search term parameter.
    term = request.getParameter("term");
    if (term==null)
      term = "";

    // Retrieve the offset and find count parameters.
    offset = getParamInt(request,"ofs",0);
    find_count = getParamInt(request,"fcount",-1);

    // Adjust the search return offset based on the command button click.
    int count = getNumResultsDisplayed();
    if (isImageButtonClicked(request,"search"))
      offset = 0;
    else if (isImageButtonClicked(request,"previous"))
    { // adjust the offset in the reverse direction
      offset -= count;
      if (offset<0)
	offset = 0;

    } // end else if
    else if (isImageButtonClicked(request,"next"))
      offset += count;  // go forwards instead
    else
      throw new ValidationException("Unable to determine what action triggered the form.");

    // Perform the search!
    List intermediate = engine.searchForUsers(field,mode,term,offset,count);
    if (find_count<0)
      find_count = engine.getSearchUserCount(field,mode,term);

    // Create the real display list by getting the community security levels.
    Iterator it = intermediate.iterator();
    Vector rc = new Vector(count+1);
    while (it.hasNext())
    { // loop around and find the member level of every one
      UserFound uf = (UserFound)(it.next());
      int new_level = comm.getMemberLevel(uf.getUID());
      if (new_level==-1)
	new_level = 0;
      rc.add(uf.createNewLevel(new_level));

    } // end while

    display_list = rc;  // save display list for display

  } // end doSearch

  public int getCommunityID()
  {
    return comm.getCommunityID();

  } // end getCommunityID

  public String getCommunityName()
  {
    return comm.getName();

  } // end getCommunityName

  public String getLocator()
  {
    return "sig=" + comm.getCommunityID();

  } // end getLocator

  public boolean displayList()
  {
    if ((display_list==null) || (display_list.size()==0))
      return false;
    if (comm_members && (display_list.size()>engine.getMaxNumCommunityMembersDisplay()))
      return false;
    return true;

  } // end displayList

  public boolean isCommunityMemberList()
  {
    return comm_members;

  } // end isCommunityMemberList

  public int getSearchField()
  {
    return field;

  } // end getSearchField

  public int getSearchMode()
  {
    return mode;

  } // end getSearchMode

  public boolean searchFieldIs(int value)
  {
    return (field==value);

  } // end searchFieldIs

  public boolean searchModeIs(int value)
  {
    return (mode==value);

  } // end searchModeIs

  public String getSearchTerm()
  {
    return term;

  } // end getSearchTerm

  public int getFindCount()
  {
    return find_count;

  } // end getFindCount

  public int getOffset()
  {
    return offset;

  } // end getOffset

  public int getSize()
  {
    return display_list.size();

  } // end getSize

  public int getNumResultsDisplayed()
  {
    return engine.getStdNumSearchResults();

  } // end getNumResultsDisplayed

  public UserFound getItem(int ndx)
  {
    return (UserFound)(display_list.get(ndx));

  } // end getItem

  public void outputDropDown(Writer out, int uid, int cur_level) throws IOException
  {
    out.write("<INPUT TYPE=HIDDEN NAME=\"zxcur_" + uid + "\" VALUE=\"" + cur_level + "\">\n");
    out.write("<SELECT NAME=\"zxnew_" + uid + "\" SIZE=1>\n");
    if (cur_level==role_comm_host.getLevel())  // cheat and put in just the host level
      out.write("<OPTION VALUE=\"" + role_comm_host.getLevel() + "\" SELECTED>"
		+ StringUtil.encodeHTML(role_comm_host.getName()) + "</OPTION>\n");
    else
    { // display all the level choices properly
      Iterator it = role_choices.iterator();
      while (it.hasNext())
      { // output the <OPTION> lines for the dropdown
	Role r = (Role)(it.next());
	out.write("<OPTION VALUE=\"" + r.getLevel() + "\"");
	if (r.getLevel()==cur_level)
	  out.write(" SELECTED");
	out.write(">" + StringUtil.encodeHTML(r.getName()) + "</OPTION>\n");

      } // end while

    } // end else

    out.write("</SELECT>\n");

  } // end outputDropDown

} // end class CommunityMembership
