package me.chyxion.tigon.mybatis;

import java.util.Map;
import java.util.List;
import java.util.Collection;
import me.chyxion.tigon.model.BaseModel;
import org.apache.ibatis.annotations.Param;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotEmpty;
import org.springframework.validation.annotation.Validated;

/**
 * @version 0.0.1
 * @since 0.0.1
 * @author Shaun Chyxion <br>
 * chyxion@163.com <br>
 * Oct 17, 2015 2:09:20 PM
 */
@Validated
@SuppressWarnings("hiding")
public interface BaseMapper<PrimaryKey, Model extends BaseModel<PrimaryKey>> {
    String PARAM_MODEL_KEY = "model";
    String PARAM_MODELS_KEY = "models";
    String PARAM_SEARCH_KEY = "s";
    String PARAM_COL_KEY = "col";
    String PARAM_COLS_KEY = "cols";

    /**
     * insert model
     * @param model model
     * @return insert result
     */
    int insert(@Param(PARAM_MODEL_KEY) Model model);

    /**
     * insert model
     * @param models model
     * @return insert result
     */
    int insert(@NotEmpty @Param(PARAM_MODELS_KEY) Collection<Model> models);

    /**
     * insert model
     * @param models model
     * @return insert result
     */
    int insert(@NotEmpty @Param(PARAM_MODELS_KEY) Model[] models);

    /**
     * update model by primary key
     * @param model update model
     * @return update result
     */
    int update(@NotNull @Param(PARAM_MODEL_KEY) Model model);

    /**
     * set col to null
     * @param col col
     * @param primaryKey primary key
     * @return update result
     */
    int setNull(@NotBlank @Param(PARAM_COL_KEY) String col, @NotNull @Param(PARAM_SEARCH_KEY) PrimaryKey primaryKey);
    
    /**
     * set col null
     * @param col col
     * @param search search
     * @return update result
     */
    int setNull(@NotBlank @Param(PARAM_COL_KEY) String col, @NotNull @Param(PARAM_SEARCH_KEY) Search search);

    /**
     * set cols null
     * @param cols cols
     * @param primaryKey primary key
     * @return update result
     */
    int setNull(@NotEmpty @Param(PARAM_COLS_KEY) String[] cols, @NotNull @Param(PARAM_SEARCH_KEY) PrimaryKey primaryKey);
    
    /**
     * set cols null
     * @param cols cols
     * @param search search
     * @return update result
     */
    int setNull(@NotEmpty @Param(PARAM_COLS_KEY) String[] cols, @NotNull @Param(PARAM_SEARCH_KEY) Search search);
    
    /**
     * set cols null
     * @param cols cols
     * @param primaryKey primary key
     * @return update result
     */
    int setNull(@NotEmpty @Param(PARAM_COLS_KEY) Collection<String> cols, @NotNull @Param(PARAM_SEARCH_KEY) PrimaryKey primaryKey);
    
    /**
     * set cols null
     * @param cols cols
     * @param search search
     * @return update result
     */
    int setNull(@NotEmpty @Param(PARAM_COLS_KEY) Collection<String> cols, @NotNull @Param(PARAM_SEARCH_KEY) Search search);
    
    /**
     * update by search
     * @param model update model
     * @param search update search
     * @return update result
     */
    int update(@NotNull @Param(PARAM_MODEL_KEY) Model model, @Param(PARAM_SEARCH_KEY) Search search);

    /**
     * update by search
     * @param update update model
     * @param search update search
     * @return update result
     */
    int update(@NotNull @Param(PARAM_MODEL_KEY) Map<String, ?> update, @Param(PARAM_SEARCH_KEY) Search search);

    /**
     * update by primary key
     * @param update update model
     * @param primaryKey primary key
     * @return update result
     */
    int update(@NotNull @Param(PARAM_MODEL_KEY) Map<String, ?> update, @Param(PARAM_SEARCH_KEY) PrimaryKey primaryKey);

    /**
     * delete by search
     * @param search search
     * @return delete result
     */
    int delete(@NotNull @Param(PARAM_SEARCH_KEY) Search search);

    /**
     * delete by PrimaryKey
     * @param primaryKey primaryKey
     * @return delete result
     */
    int delete(@NotNull @Param(PARAM_SEARCH_KEY) PrimaryKey primaryKey);

    /**
     * find one by search
     * @param search search
     * @return true if exists rows
     */
    boolean exists(@Param(PARAM_SEARCH_KEY) Search search);

    /**
     * find one by search
     * @param search search
     * @return find result or null
     */
    Model find(@NotNull @Param(PARAM_SEARCH_KEY) Search search);

    /**
     * find one by PrimaryKey
     * @param primaryKey primaryKey
     * @return find result or null
     */
    Model find(@NotNull @Param(PARAM_SEARCH_KEY) PrimaryKey primaryKey);

    /**
     * list by search
     * @param search search
     * @return list result or empty list
     */
    List<Model> list(@Param(PARAM_SEARCH_KEY) Search search);

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