package cc.smtweb.framework.core.db.vo;

import cc.smtweb.framework.core.annotation.SwTable;
import cc.smtweb.framework.core.common.SwConsts;
import cc.smtweb.framework.core.common.SwEnum;
import cc.smtweb.framework.core.db.DbEngine;
import cc.smtweb.framework.core.db.cache.ModelDatabaseCache;
import cc.smtweb.framework.core.db.cache.ModelTableCache;
import cc.smtweb.framework.core.db.impl.DefaultEntity;
import cc.smtweb.framework.core.util.JsonUtil;
import org.apache.commons.lang3.StringUtils;

import java.util.ArrayList;
import java.util.List;

@SwTable(value = "ASP_MODEL_TABLE")
public class ModelTable extends DefaultEntity {
    public final static String ENTITY_NAME = "ASP_MODEL_TABLE";

    /*冗余*/
    private String idField;

    private List<ModelField> fields = new ArrayList<>();
    private List<ModelIndex> indexes = new ArrayList<>();
    private List<ModelCache> caches = new ArrayList<>();

    public ModelTable() {
        super(ENTITY_NAME);
    }

    public long getId() {
        return getLong("tb_id");
    }

    public void setId(long tbId) {
        put("tb_id", tbId);
    }

    public long getPrjId() {
        return getLong("tb_prj_id");
    }

    public void setPrjId(long tbPrjId) {
        put("tb_prj_id", tbPrjId);
    }

    public long getMcId() {
        return getLong("tb_mc_id");
    }

    public void setMcId(long tbMcId) {
        put("tb_mc_id", tbMcId);
    }

    public long getDbId() {
        return getLong("tb_db_id");
    }

    public void setDbId(long tbDbId) {
        put("tb_db_id", tbDbId);
    }

    public String getExtends() {
        return getStr("tb_extends");
    }

    public void setExtends(String tbExtends) {
        put("tb_extends", tbExtends);
    }

    public String getName() {
        return getStr("tb_name");
    }

    public void setName(String tbName) {
        put("tb_name", tbName);
    }

    public String getTitle() {
        return getStr("tb_title");
    }

    public void setTitle(String tbTitle) {
        put("tb_title", tbTitle);
    }

    public String getAbbr() {
        return getStr("tb_abbr");
    }

    public void setAbbr(String tbAbbr) {
        put("tb_abbr", tbAbbr);
    }

    public int getType() {
        return getInt("tb_type");
    }

    public void setType(int tbType) {
        put("tb_type", tbType);
    }

    public boolean isNeedCache() {
        return getBool("tb_need_cache");
    }

    public void setNeedCache(boolean tbNeedCache) {
        setBool("tb_need_cache", tbNeedCache);
    }

    public String getContent() {
        return getStr("tb_content");
    }

    public long getCreateUid() {
        return getLong("tb_create_uid");
    }

    public void setCreateUid(long tbCreateUid) {
        put("tb_create_uid", tbCreateUid);
    }

    public long getUpdateUid() {
        return getLong("tb_update_uid");
    }

    public void setUpdateUid(long tbUpdateUid) {
        put("tb_update_uid", tbUpdateUid);
    }

    public long getCreateAt() {
        return getLong("tb_create_at");
    }

    public void setCreateAt(long tbCreateAt) {
        put("tb_create_at", tbCreateAt);
    }

    public long getUpdateAt() {
        return getLong("tb_update_at");
    }

    public void setUpdateAt(long tbUpdateAt) {
        put("tb_update_at", tbUpdateAt);
    }

    public String getIdField() {
        return idField;
    }

    public String getDbName() {
        return ModelDatabaseCache.getInstance().getName(getDbId());
    }

    public List<ModelField> getFields() {
        return fields;
    }

    public List<ModelIndex> getIndexes() {
        return indexes;
    }

    public List<ModelCache> getCaches() {
        return caches;
    }

    public ModelField findField(String fieldName) {
        if (fieldName != null && fields != null) {
            for (ModelField modelField : fields) {
                if (fieldName.equals(modelField.getName())) {
                    return modelField;
                }
            }
        }

        return null;
    }

    public String findFieldTitle(String fieldName) {
        ModelField field = findField(fieldName);
        return field != null ? field.getTitle(): fieldName;
    }

    public String fullName() {
        return getDbName() + '.' + getName();
    }

    public void addIndex(ModelIndex modelIndex) {
        indexes.add(modelIndex);
    }

    public ModelIndex findIndexByName(String indexName) {
        for (ModelIndex modelIndex : indexes) {
            if (indexName.equals(modelIndex.getName())) {
                return modelIndex;
            }
        }

        return null;
    }

    public ModelIndex findPrimaryIndex() {
        for (ModelIndex modelIndex : indexes) {
            if (ModelIndex.TYPE_PRIMARY.equalsIgnoreCase(modelIndex.getType())) {
                return modelIndex;
            }
        }

        return null;
    }

    public ModelField findFieldByName(String name) {
        if (name != null) {
            for (ModelField value : fields) {
                if (name.equalsIgnoreCase(value.getName())) {
                    return value;
                }
            }
        }

        return null;
    }

    public ModelField findFieldByType(int type) {
        for (ModelField value : fields) {
            if (type == value.getFieldType()) {
                return value;
            }
        }

        return null;
    }

    public String findFieldNameByType(int type) {
        for (ModelField value : fields) {
            if (type == value.getFieldType()) {
                return value.getName();
            }
        }

        return null;
    }

    public ModelField findIdField() {
        ModelIndex index = findPrimaryIndex();
        if (index != null) {
            return findField(index.getFields());
        }

        return null;
    }

    public List<ModelLinkName> findLinkeNames() {
        List<ModelLinkName> list = new ArrayList<>();
        for (ModelField field : fields) {
            if (field.getLink() <= 0) {
                continue;
            }
            ModelTable linkTable = ModelTableCache.getInstance().get(field.getLink());
            if (linkTable == null) {
                continue;
            }
            ModelField linkNameField = linkTable.findFieldByType(SwEnum.FieldType.NAME.value);
            if (linkNameField != null) {
                list.add(new ModelLinkName(field.getName(), linkTable, linkNameField.getName()));
            }
        }
        return list;
    }

    public void setContent(String tableContent) {
        put("tb_content", tableContent);
        //读取表定义信息
        ModelTable bean = JsonUtil.parse(tableContent, ModelTable.class);
        if (bean == null) {
            return;
        }
        this.fields = bean.fields;
        this.indexes = bean.indexes;
        this.caches = bean.caches;
        ModelIndex i = findPrimaryIndex();
        if (i != null) {
            this.idField = i.getFields();
        }
    }

    public String getSchemaTableName() {
        String dbName = getDbName();
        if (StringUtils.isEmpty(dbName) || dbName.equals(SwConsts.DEF_DB_NAME))
            return DbEngine.getInstance().getDbSchema() + "." + getName();
        return DbEngine.getInstance().getDbSchema() + "_" + dbName + "." + getName();
    }
}
