package me.chyxion.tigon.service;

import java.util.List;
import java.util.function.Function;
import me.chyxion.tigon.mybatis.Search;
import javax.validation.constraints.Min;
import me.chyxion.tigon.model.BaseModel;
import me.chyxion.tigon.model.ViewModel;
import me.chyxion.tigon.model.ListResult;
import javax.validation.constraints.NotNull;
import org.springframework.validation.annotation.Validated;
import me.chyxion.tigon.validation.annotation.NotNullOrBlank;

/**
 * @version 0.0.1
 * @since 0.0.1
 * @author Shaun Chyxion <br>
 * chyxion@163.com <br>
 * Aug 11, 2016 1:36:04 PM
 */
@Validated
public interface BaseQueryService<PrimaryKey,
    Model extends BaseModel<PrimaryKey>>
    extends BaseService<PrimaryKey, Model> {

    /**
     * find model by primaryKey
     * @param primaryKey model primaryKey
     * @return model
     */
    Model find(@NotNullOrBlank PrimaryKey primaryKey);

    /**
     * find model by search
     * @param search search
     * @return result
     */
    Model find(@NotNull Search search);

    /**
     * list by search
     * @param search search
     * @return list result
     */
    @NotNull List<Model> list(Search search);

    /**
     * count by search
     * @param search search
     * @return count
     */
    int count(Search search);

    /**
     * find view model by search
     * @param search search
     * @return view model
     */
    ViewModel<Model> findViewModel(@NotNull Search search);

    /**
     * find view model by primaryKey
     * @param primaryKey primaryKey
     * @return view model
     */
    ViewModel<Model> findViewModel(@NotNull PrimaryKey primaryKey);

    /**
     * list view model
     * @param search search
     * @return view model
     */
    @NotNull List<ViewModel<Model>> listViewModels(@NotNull Search search);

    /**
     * list view model page
     * @param search search
     * @return view model page
     */
    @NotNull ListResult<ViewModel<Model>> listViewModelsPage(@NotNull Search search);
    
    /**
     * list page by search
     * @param search search
     * @return list result
     */
    @NotNull ListResult<Model> listPage(@NotNull Search search);

    /**
     * scan model of all
     * @param scanner scanner
     */
    Model scan(@NotNull Function<Model, Boolean> scanner);
    
    /**
     * scan model by search
     * @param search search
     * @param scanner scanner
     */
    Model scan(Search search, @NotNull Function<Model, Boolean> scanner);
    
    /**
     * scan model by search
     * @param batchSize fetch model batch size
     * @param search search
     * @param scanner scanner
     */
    Model scan(@Min(1) int batchSize, Search search, @NotNull Function<Model, Boolean> scanner);

    <Model> Model scan(@Min(1) int batchSize,
       Search search,
       @NotNull Function<Search, List<Model>> dataQuerier,
       @NotNull Function<Search, Integer> countQuerier,
       @NotNull Function<Model, Boolean> scanner);
}
