/* ===================================================================
 * RecipeSearchBiz.java
 * 
 * Created Sep 15, 2004 5:07:32 PM
 * 
 * Copyright (c) 2004 Matt Magoffin (spamsqr@msqr.us)
 * 
 * This program is free software; you can redistribute it and/or 
 * modify it under the terms of the GNU General Public License as 
 * published by the Free Software Foundation; either version 2 of 
 * the License, or (at your option) any later version.
 * 
 * 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., 59 Temple Place, Suite 330, Boston, MA 
 * 02111-1307 USA
 * ===================================================================
 * $Id: RecipeSearchBiz.java 33 2009-05-04 03:35:14Z msqr $
 * ===================================================================
 */

package magoffin.matt.ieat.biz;

import java.util.List;

import magoffin.matt.ieat.domain.RecipeSearchCriteria;
import magoffin.matt.ieat.domain.UiSearchResults;
import magoffin.matt.ieat.domain.UiUserMatch;
import magoffin.matt.ieat.domain.Unit;

/**
 * Business interface for searching recipes.
 * 
 * <p>This interface is separate from the RecipeBiz so that 
 * different search implementations can be used, for example 
 * JDBC versus Lucene.</p>
 * 
 * <p>The <code>ADVANCED_SEARCH_*_TYPE</code> constants are the 
 * required advanced search types that must be supported. 
 * The <code>ADVANCED_SEARCH_OP_*</code> constants are the search 
 * operation constants that overall must be supported, but not 
 * necessarily for every search type.</p>
 * 
 * @author Matt Magoffin (spamsqr@msqr.us)
 * @version $Revision: 33 $ $Date: 2009-05-04 15:35:14 +1200 (Mon, 04 May 2009) $
 */
public interface RecipeSearchBiz {
	
	/** The default length of top-level index section names. */
	public static final int DEFAULT_TOP_LEVEL_INDEX_SECTION_NAME_LENGTH = 1;
	
	/** The recipe search mode for a simple search. */
	public static final String RECIPE_SEARCH_MODE_SIMPLE = "simple";
	
	/** The recipe search mode to find recipes containing specific ingredients. */
	public static final String RECIPE_SEARCH_MODE_BY_INGREDIENT = "ingredient";
	
	/** The recipe search mode to find recipes via advanced criteria. */
	public static final String RECIPE_SEARCH_MODE_ADVANCED = "advanced";
	
	/** The advanced search type for finding by average user rating. */
	public static final char ADVANCED_SEARCH_RATING_TYPE = '1';
	
	/** The advanced search type for finding by general text. */
	public static final char ADVANCED_SEARCH_TEXT_TYPE = '2';
	
	/** The advanced search type for finding by the author an object. */
	public static final char ADVANCED_SEARCH_AUTHOR_TYPE = '3';
	
	/** The advanced search type for finding by a specific user's rating. */
	public static final char ADVANCED_SEARCH_USER_RATING_TYPE = '4';
	
	/** The advanced search operation for equality matching. */
	public static final short ADVANCED_SEARCH_OP_IS = 1;
	
	/** The advanced search operation for negated equality matching. */
	public static final short ADVANCED_SEARCH_OP_IS_NOT = 2;
	
	/** The advanced search operation for less-than matching. */
	public static final short ADVANCED_SEARCH_OP_LESS_THAN = 3;
	
	/** The advanced search operation for greater-than matching. */
	public static final short ADVANCED_SEARCH_OP_GREATER_THAN = 4;
	
	/** The advanced search operation for substring matching. */
	public static final short ADVANCED_SEARCH_OP_CONTAINS = 5;
	
	/** The advanced search operation for negated substring matching. */
	public static final short ADVANCED_SEARCH_OP_DOES_NOT_CONTAIN = 6;
	
	/**
	 * A criteria for index search operations.
	 */
	public static interface IndexCriteria {
		/**
		 * The index section to display, or <em>null</em> to 
		 * dislpay the first available section.
		 * 
		 * @return the display section
		 */
		public String getDisplaySection();
		
		/**
		 * The maximum number of results to show, or if less than 
		 * 1 unlimited results.
		 * 
		 * @return the page size
		 */
		public int getPageSize();
		
		/**
		 * The starting result "page" offset, starting at 0.
		 * 
		 * @return the page offset
		 */
		public int getPageStart();
	}
	
	/**
	 * A search criteria for Ingredient objects.
	 */
	public static interface IngredientCriteria {
		
		/**
		 * The name of the ingredient to search for.
		 * 
		 * @return the name
		 */
		public String getIngredientName();
		
		/**
		 * If <em>true</em> then use an approximate search algorithm.
		 * 
		 * @return boolean
		 */
		public boolean useApproximateSearch();
		
		/**
		 * Return <em>true</em> if only a count is desired.
		 * @return boolean
		 */
		public boolean isCountOnly();
	}
	
	/**
	 * A search criteria for User objects.
	 */
	public static interface UserCriteria {
		
		/** 
		 * Search mode for finding all users matching any of the Integer 
		 * user ID values in the {@link #getUserIds()} array.
		 * 
		 * <p>Note duplicate users should not be returned, and the returned 
		 * order should not be assumed to be sorted.</p>
		 */
		public static final int MODE_USERS_BY_ID = 1;
		
		/**
		 * Search mode for finding a user matching a login value available
		 * via the {@link #getQuery()} value.
		 */
		public static final int MODE_USER_BY_LOGIN = 2;
		
		/**
		 * Get the search mode.
		 * @return search mode
		 */
		public int getSearchMode();
		
		/**
		 * Get the user IDs to search for.
		 * @return list of user ids.
		 */
		public Integer[] getUserIds();
		
		/**
		 * Get a string query to search for.
		 * 
		 * @return the query string
		 */
		public String getQuery();
		
		/**
		 * Return <em>true</em> if only a count is desired.
		 * @return boolean
		 */
		public boolean isCountOnly();
	}
	
	/**
	 * A search criteria for Unit objects.
	 */
	public static interface UnitCriteria {
		/**
		 * The name of the unit to search for.
		 * 
		 * @return the name
		 */
		public Unit getUnit();
		
		/**
		 * If <em>true</em> then use an approximate search algorithm.
		 * 
		 * @return boolean
		 */
		public boolean useApproximateSearch();
		
		/**
		 * Return <em>true</em> if only a count is desired.
		 * @return boolean
		 */
		public boolean isCountOnly();
	}
	
	/**
	 * Get the UiRecipeMatch objects for a given index.
	 * 
	 * <p>The returned <code>UiSearchResults</code> object will have a
	 * <code>UiIndex</code> object populated with index section data.
	 * The UiSearchResults's <code>recipe</code> list will contain 
	 * the list of recipe matches whose name's start with <coode>displaySection</code>.
	 * If <code>displaySection</code> is <em>null</em> then the first 
	 * index section with recipes available should be populated.</p>
	 * 
	 * @param criteria 
	 * @return the search results
	 */
	public UiSearchResults findRecipesForIndex(IndexCriteria criteria);
	
	/**
	 * Get a list of UiIngredientMatch objects that are similaryly named
	 * to an ingredient name.
	 * 
	 * <p>This method is to be used to find possible duplicate ingredients, 
	 * for example while attempting to add a new ingredient to the system.
	 * The list of returned ingredient matches represent possible duplicates
	 * to the ingredient name passed via the criteria parameter.</p>
	 * 
	 * @param criteria the search criteria
	 * @return the search results
	 */
	public UiSearchResults findIngredientsSimilarlyNamed(IngredientCriteria criteria);
	
	/**
	 * Get the UiUserMatch objects for a given index.
	 * 
	 * <p>The returned <code>UiSearchResults</code> object will have a
	 * <code>UiIndex</code> object populated with index section data.
	 * The UiSearchResults's <code>user</code> list will contain 
	 * the list of user matches whose name's start with <coode>displaySection</code>.
	 * If <code>displaySection</code> is <em>null</em> then the first 
	 * index section with recipes available should be populated.</p>
	 * 
	 * @param criteria 
	 * @return the search results
	 */
	public UiSearchResults findUsersForIndex(IndexCriteria criteria);
	
	/**
	 * Get a list of UiRecipeMatch objects that match a given criteria.
	 * @param criteria the criteria to use for searching
	 * @param context the current context
	 * @return the search results
	 */
	public UiSearchResults findRecipes(RecipeSearchCriteria criteria, BizContext context);
	
	/**
	 * Get a Unit object that is similarly named to the Unit criteria.
	 * @param criteria the Unit to use as criteria
	 * @return the similar Unit, or <em>null</em> if none found
	 */
	public Unit findUnitSimilarlyNamed(Unit criteria);
	
	/**
	 * Lower-level API for searching for users.
	 * 
	 * <p>This method returns a List of {@link magoffin.matt.ieat.domain.UiUserMatch}
	 * objects that match the search criteria. It is meant as 
	 * an aid for actions which need to use search result data as part 
	 * of their process but not a full <code>UiSearchResults</code> 
	 * object.</p>
	 * 
	 * @param criteria the search criteria
	 * @return non-null List of <code>UiUserMatch</code> objects matching 
	 * the search criteria
	 */
	public List<UiUserMatch> searchForUsers(UserCriteria criteria);

}
