package com.uas.search.service;

import com.uas.search.annotation.NotEmpty;
import com.uas.search.constant.model.CollectField;
import com.uas.search.constant.model.PageParams;
import com.uas.search.constant.model.PageParams.FilterField;
import com.uas.search.constant.model.SPage;
import com.uas.search.exception.SearchException;
import com.uas.search.model.Brand;
import com.uas.search.model.Component;
import com.uas.search.model.Goods;
import com.uas.search.model.Kind;

import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * 搜索服务的接口
 * 
 * @author suntg
 * @since 2016年7月29日下午4:58:45
 */
public interface SearchService {

	/**
	 * 根据关键字搜索产品类目id
	 * 
	 * @param keyword
	 *            关键词
	 * @param page
	 *            页码
	 * @param size
	 *            页大小
	 * @return 符合条件的类目id
	 * @throws SearchException
	 */
	public SPage<Long> getKindIds(String keyword, Integer page, Integer size) throws SearchException;

	/**
	 * 根据关键词搜索产品类目
	 * 
	 * @param keyword
	 *            关键词
	 * @param page
	 *            页码
	 * @param size
	 *            页大小
	 * @return
	 * @throws SearchException
	 */
	public SPage<Map<String, Object>> getKinds(String keyword, Integer page, Integer size) throws SearchException;

	/**
	 * 根据关键词搜索产品品牌id
	 * 
	 * @param keyword
	 *            关键词
	 * @param page
	 *            页码
	 * @param size
	 *            页大小
	 * @return 符合条件的品牌id
	 * @throws SearchException
	 */
	public SPage<Long> getBrandIds(String keyword, Integer page, Integer size) throws SearchException;

	/**
	 * 根据关键词搜索产品品牌
	 * 
	 * @param keyword
	 *            关键词
	 * @param page
	 *            页码
	 * @param size
	 *            页大小
	 * @return 符合条件的品牌
	 * @throws SearchException
	 */
	public SPage<Map<String, Object>> getBrands(String keyword, Integer page, Integer size) throws SearchException;

	/**
	 * 根据关键词搜索产品（关键词可能是器件、类目、品牌，甚至可能是类目、品牌的混合）
	 * 
	 * @param keyword
	 *            关键词
	 * @param params
	 *            翻页、过滤等信息
	 *            <p>
	 *            关于过滤，通过键值对指定过滤条件，键为
	 *            {@link com.uas.search.constant.model.PageParams.FilterField}
	 *            ，值的类型由键决定：
	 *            </p>
	 * 
	 *            <table border=1 cellpadding=5 cellspacing=0 summary=
	 *            "Fields and types">
	 *            <tr>
	 *            <th>Field</th>
	 *            <th>Type</th>
	 *            </tr>
	 *            <tr>
	 *            <td>COMPONENT_KINDID</td>
	 *            <td>Long</td>
	 *            </tr>
	 *            <tr>
	 *            <td>COMPONENT_BRANDID</td>
	 *            <td>Long</td>
	 *            </tr>
	 *            <tr>
	 *            <td>COMPONENT_PROPERTIES</td>
	 *            <td>键值对，键值分别为属性id、属性值</td>
	 *            </tr>
	 *            <tr>
	 *            <td>COMPONENT_HAS_RESERVE</td>
	 *            <td>Boolean</td>
	 *            </tr>
	 *            <tr>
	 *            <td>COMPONENT_HAS_SAMPLE</td>
	 *            <td>Boolean</td>
	 *            </tr>
	 *            <tr>
	 *            <td>COMPONENT_HAS_ORIGINAL</td>
	 *            <td>Boolean</td>
	 *            </tr>
	 *            <tr>
	 *            <td>COMPONENT_HAS_INACTION_STOCK</td>
	 *            <td>Boolean</td>
	 *            </tr>
	 *            </table>
	 * 
	 * @return
	 * @throws SearchException
	 */
	public Map<String, Object> getComponentIds(String keyword, PageParams params) throws SearchException;

	/**
	 * 根据产品搜索获取产品类目id的统计
	 * 
	 * @param keyword
	 * @param brandId
	 *            （可选）
	 * @return
	 * @throws SearchException
	 */
	public Set<Long> getKindIdsBySearchComponent(String keyword, String brandId) throws SearchException;

	/**
	 * 根据产品搜索获取产品类目的统计
	 * 
	 * @param keyword
	 * @param brandId
	 *            （可选）
	 * @return
	 * @throws SearchException
	 */
	public Set<Map<String, Object>> getKindsBySearchComponent(String keyword, String brandId) throws SearchException;

	/**
	 * 根据产品搜索获取产品品牌id的统计
	 * 
	 * @param keyword
	 * @param kindId
	 *            （可选）
	 * @return
	 * @throws SearchException
	 */
	public Set<Long> getBrandIdsBySearchComponent(String keyword, String kindId) throws SearchException;

	/**
	 * 根据产品搜索获取产品品牌的统计
	 * 
	 * @param keyword
	 * @param kindId
	 *            （可选）
	 * @return
	 * @throws SearchException
	 */
	public Set<Map<String, Object>> getBrandsBySearchComponent(String keyword, String kindId) throws SearchException;

	/**
	 * 根据输入获取联想词（包括器件、类目、品牌，按顺序获取，数量不足，才会获取下一个）
	 * 
	 * @param keyword
	 * @param size 指定的联想词数目
	 * @return
	 * @throws SearchException
	 */
	public List<String> getSimilarKeywords(String keyword, Integer size) throws SearchException;

	/**
	 * 根据输入的原厂型号获取联想词
	 * 
	 * @param componentCode
	 * @param size 指定的联想词数目
	 * @return 包括id、uuid、code
	 * @throws SearchException
	 */
	public List<Map<String, Object>> getSimilarComponents(String componentCode, Integer size) throws SearchException;

	/**
	 * 根据输入的品牌获取联想词
	 * 
	 * @param brandName
	 * @param size 指定的联想词数目
	 * @return 包括id、uuid、nameCn、nameEn
	 * @throws SearchException
	 */
	public List<Map<String, Object>> getSimilarBrands(String brandName, Integer size) throws SearchException;

	/**
	 * 根据输入的类目名获取联想词
	 * 
	 * @param kindName
	 * @param size 指定的联想词数目
	 * @return 包括id、nameCn、level、isLeaf
	 * @throws SearchException
	 */
	public List<Map<String, Object>> getSimilarKinds(String kindName, Integer size) throws SearchException;

	/**
	 * 根据输入的类目名获取末级类目联想词
	 * 
	 * @param kindName
	 * @param size 指定的联想词数目
	 * @return 包括id、nameCn、level、isLeaf
	 * @throws SearchException
	 */
	public List<Map<String, Object>> getSimilarLeafKinds(String kindName, Integer size) throws SearchException;

	/**
	 * 根据输入的类目名和指定的类目级别获取联想词
	 * 
	 * @param kindName
	 * @param level
	 * @param size 指定的联想词数目
	 * @return 包括id、nameCn、level、isLeaf
	 * @throws SearchException
	 */
	public List<Map<String, Object>> getSimilarKindsByLevel(String kindName, Short level, Integer size) throws SearchException;

	/**
	 * 根据类目id、属性id、属性值获取联想词
	 * 
	 * @param kindId
	 *            类目id
	 * @param propertyId
	 *            属性id
	 * @param keyword
	 *            （可选） 属性值（部分字符）
	 * @param topNum
	 *            （可选） 获取的最大数目
	 * @return 相似的属性值，包括propertyValue
	 * @throws SearchException
	 */
	public List<Map<String, String>> getSimilarPropertyValues(Long kindId, Long propertyId, String keyword, Long topNum)
			throws SearchException;

	/**
	 * 根据关键词搜索批次（关键词可能是器件、类目、品牌）
	 * 
	 * @param keyword
	 *            关键词
	 * @param pageParams
	 *            翻页、过滤、排序等信息
	 *            <p>
	 *            关于过滤，通过键值对指定过滤条件，键为
	 *            {@link com.uas.search.constant.model.PageParams.FilterField}
	 *            ，值的类型由键决定：
	 *            </p>
	 * 
	 *            <table border=1 cellpadding=5 cellspacing=0 summary=
	 *            "Fields and types">
	 *            <tr>
	 *            <th>Field</th>
	 *            <th>Type</th>
	 *            </tr>
	 *            <tr>
	 *            <td>GOODS_KINDID</td>
	 *            <td>List(Long)</td>
	 *            </tr>
	 *            <tr>
	 *            <td>GOODS_BRANDID</td>
	 *            <td>List(Long)</td>
	 *            </tr>
	 *            <tr>
	 *            <td>GOODS_STORE_TYPE</td>
	 *            <td>List(String)</td>
	 *            </tr>
	 *            <tr>
	 *            <td>GOODS_CRNAME</td>
	 *            <td>List(String)</td>
	 *            </tr>
	 *            <tr>
	 *            <td>GOODS_MINPRICERMB</td>
	 *            <td>Double</td>
	 *            </tr>
	 *            <tr>
	 *            <td>GOODS_MAXPRICERMB</td>
	 *            <td>Double</td>
	 *            </tr>
	 *            <tr>
	 *            <td>GOODS_MINPRICEUSD</td>
	 *            <td>Double</td>
	 *            </tr>
	 *            <tr>
	 *            <td>GOODS_MAXPRICEUSD</td>
	 *            <td>Double</td>
	 *            </tr>
	 *            </table>
	 * 
	 * @return 器件id、批次id和分页信息
	 */
	public Map<String, Object> getGoodsIds(String keyword, PageParams pageParams) throws SearchException;

	/**
	 * 搜索批次时，统计指定信息
	 * 
	 * @param keyword
	 *            关键词
	 * @param collectedField
	 *            需要统计的信息
	 * @param filters
	 *            过滤条件，值的类型由键决定：
	 * 
	 *            <table border=1 cellpadding=5 cellspacing=0 summary=
	 *            "Fields and types">
	 *            <tr>
	 *            <th>Field</th>
	 *            <th>Type</th>
	 *            </tr>
	 *            <tr>
	 *            <td>GOODS_KINDID</td>
	 *            <td>List(Long)</td>
	 *            </tr>
	 *            <tr>
	 *            <td>GOODS_BRANDID</td>
	 *            <td>List(Long)</td>
	 *            </tr>
	 *            <tr>
	 *            <td>GOODS_STORE_TYPE</td>
	 *            <td>List(String)</td>
	 *            </tr>
	 *            <tr>
	 *            <td>GOODS_CRNAME</td>
	 *            <td>List(String)</td>
	 *            </tr>
	 *            </table>
	 * 
	 * @return 统计的信息（由collectedField决定）
	 * 
	 *         <table border=1 cellpadding=5 cellspacing=0 summary=
	 *         "Collected fields and messages">
	 *         <tr>
	 *         <th>Collected field</th>
	 *         <th>Message</th>
	 *         </tr>
	 *         <tr>
	 *         <td>GOODS_KIND</td>
	 *         <td>ki_id、ki_name_cn</td>
	 *         </tr>
	 *         <tr>
	 *         <td>GOODS_BRAND</td>
	 *         <td>br_id、br_uuid、br_name_cn、br_name_en</td>
	 *         </tr>
	 *         <tr>
	 *         <td>GOODS_STORE_TYPE</td>
	 *         <td>store_type</td>
	 *         </tr>
	 *         <tr>
	 *         <td>GOODS_CRNAME</td>
	 *         <td>cr_name</td>
	 *         </tr>
	 *         </table>
	 */
	public List<Map<String, Object>> collectBySearchGoods(String keyword, CollectField collectedField,
			Map<FilterField, Object> filters);

	/**
	 * 根据id获取类目
	 * 
	 * @param id
	 * @return
	 */
	public Kind getKind(Long id);

	/**
	 * 根据id获取品牌
	 * 
	 * @param id
	 * @return
	 */
	public Brand getBrand(Long id);

	/**
	 * 根据id获取器件
	 * 
	 * @param id
	 * @return
	 */
	public Component getComponent(Long id);

	/**
	 * 根据id获取批次
	 * 
	 * @param id
	 * @return
	 */
	public Goods getGoods(String id);

	/**
	 * 分页获取本地指定表的索引中的数据
	 * 
	 * @param tableName
	 *            表名
	 * @param keyword
	 *            关键词，可为空，默认正则搜索空串
	 * @param field
	 *            搜索字段，可为空，默认取各表索引中的id字段
	 * @param tokenized
	 *            是否分词，可为空，默认不分词
	 * @param page
	 *            页码
	 * @param size
	 *            分页大小
	 * @return
	 */
	public SPage<Object> getObjects(String tableName, String keyword, String field, Boolean tokenized, @NotEmpty("page") Integer page, @NotEmpty("size") Integer size);

}
