package {{packageName}}.core.{{entity.module}}.service;

import java.io.Serializable;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.HashMap;
import java.util.Collection;
import java.math.BigInteger;

import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.scheduling.annotation.Async;
import com.alibaba.fastjson.JSONObject;
import org.springframework.cache.annotation.CacheEvict;

import com.baomidou.mybatisplus.extension.service.IService;
import com.baomidou.dynamic.datasource.annotation.DS;
import cn.ibizlab.util.helper.CachedBeanCopier;
import cn.ibizlab.util.security.SpringContextHolder;
import {{packageName}}.core.{{entity.module}}.domain.{{entity.codeName}};
import {{packageName}}.core.{{entity.module}}.filter.{{entity.codeName}}SearchContext;
{{#entity.relEntities}}
import {{packageName}}.core.{{module}}.domain.{{codeName}};
{{/entity.relEntities}}

{{#dsName}}
@DS("{{entity.dataSource}}")
{{/dsName}}
public interface {{entity.codeName}}Service {

    default {{entity.codeName}}Service getSelf() {
        return SpringContextHolder.getBean(this.getClass());
    }

    {{entity.codeName}} get({{entity.codeName}} et);
    default {{entity.codeName}} get({{entity.keyField.type.java}} key) {
        {{entity.codeName}} et = new {{entity.codeName}}();
        et.set{{pascalCase entity.keyField.codeName}}(key);
        return get(et);
    }
    default List<{{entity.codeName}}> getByIds(Collection<{{entity.keyField.type.java}}> ids) {
        List<{{entity.codeName}}> entities =new ArrayList();
        ids.forEach(key -> {
            {{entity.codeName}} et = new {{entity.codeName}}();
            et.set{{pascalCase entity.keyField.codeName}}(key);
            entities.add(et);
        });
        return getByEntities(entities);
    }
    List<{{entity.codeName}}> getByEntities(List<{{entity.codeName}}> entities);

    {{entity.codeName}} getDraft({{entity.codeName}} et);

    Integer checkKey({{entity.codeName}} et);

    boolean create({{entity.codeName}} et);
    {{#entity.enableEntityCache}}
    @CacheEvict(value = "{{lowerCase entity.codeName}}", allEntries = true)
    {{/entity.enableEntityCache}}
    boolean createBatch(List<{{entity.codeName}}> list);

    boolean update({{entity.codeName}} et);
    {{#entity.enableEntityCache}}
    @CacheEvict(value = "{{lowerCase entity.codeName}}", allEntries = true)
    {{/entity.enableEntityCache}}
    boolean updateBatch(List<{{entity.codeName}}> list);

    boolean save({{entity.codeName}} et);
    {{#entity.enableEntityCache}}
    @CacheEvict(value = "{{lowerCase entity.codeName}}", allEntries = true)
    {{/entity.enableEntityCache}}
    boolean saveBatch(List<{{entity.codeName}}> list);

    default boolean remove({{entity.keyField.type.java}} key) {
        {{entity.codeName}} et = new {{entity.codeName}}();
        et.set{{pascalCase entity.keyField.codeName}}(key);
        return remove(et);
    }
    default boolean remove(List<{{entity.keyField.type.java}}> key) {
        return removeBatch(key);
    }
    {{#entity.enableEntityCache}}
    @CacheEvict(value = "{{lowerCase entity.codeName}}", key = "'row:'+#p0.{{camelCase entity.keyField.codeName}}")
    {{/entity.enableEntityCache}}
    boolean remove({{entity.codeName}} et);

    default boolean removeBatch(Collection<{{entity.keyField.type.java}}> ids) {
        List<{{entity.codeName}}> entities =new ArrayList();
        ids.forEach(key -> {
            {{entity.codeName}} et = new {{entity.codeName}}();
            et.set{{pascalCase entity.keyField.codeName}}(key);
            entities.add(et);
        });
        return getSelf().removeByEntities(entities);
    }

    boolean removeByEntities(List<{{entity.codeName}}> entities);

    {{#each entity.extActions}}
    default {{outParam}} {{camelCase codeName}}({{inParam}} {{inParamName}}) {
        {{#if voidReturn}}
        return {{inParamName}};
        {{else}}
        return null;
        {{/if}}
    }

    {{/each}}
    {{#entity.dataSets}}
    Page<{{entity.codeName}}> search{{pascalCase codeName}}({{entity.codeName}}SearchContext context);
    List<{{entity.codeName}}> list{{pascalCase codeName}}({{entity.codeName}}SearchContext context);

    {{/entity.dataSets}}
    {{#if entity.hasDupCheck}}
    default {{entity.codeName}}SearchContext getSearchContext() {
        return new {{entity.codeName}}SearchContext();
    }
    {{/if}}
    {{#entity.references}}
    List<{{entity.codeName}}> selectBy{{pascalCase fkField.codeName}}({{fkField.type.java}} {{camelCase fkField.codeName}});
    {{#entity.enableEntityCache}}
    @CacheEvict(value = "{{lowerCase entity.codeName}}", allEntries = true)
    {{/entity.enableEntityCache}}
    boolean removeBy{{pascalCase fkField.codeName}}({{fkField.type.java}} {{camelCase fkField.codeName}});
    {{#entity.enableEntityCache}}
    @CacheEvict(value = "{{lowerCase entity.codeName}}", allEntries = true)
    {{/entity.enableEntityCache}}
    boolean resetBy{{pascalCase fkField.codeName}}({{fkField.type.java}} {{camelCase fkField.codeName}});
    {{#entity.enableEntityCache}}
    @CacheEvict(value = "{{lowerCase entity.codeName}}", allEntries = true)
    {{/entity.enableEntityCache}}
    boolean saveBy{{pascalCase fkField.codeName}}({{fkField.type.java}} {{camelCase fkField.codeName}},List<{{entity.codeName}}> list);

    {{/entity.references}}
    {{#each entity.nesteds}}
        {{#if listCode}}
        {{#unless columnName}}
    List<{{entityCodeName}}> get{{pascalCase codeName}}({{entity.codeName}} et);

        {{/unless}}
        {{/if}}
    {{/each}}
}