package cn.ibizlab.codegen.model;

import cn.ibizlab.codegen.utils.DataObject;
import cn.ibizlab.codegen.utils.StringAdvUtils;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import lombok.experimental.Accessors;
import net.ibizsys.model.database.IPSDEFDTColumn;
import net.ibizsys.model.dataentity.IPSDataEntity;
import net.ibizsys.model.dataentity.defield.IPSDEField;
import net.ibizsys.model.dataentity.defield.IPSLinkDEField;
import net.ibizsys.model.dataentity.der.*;
import net.ibizsys.model.dataentity.ds.IPSDEDataQueryCodeCond;
import net.ibizsys.model.dataentity.ds.IPSDEDataSetGroupParam;
import net.ibizsys.model.dataentity.ds.PSDEDataSetGroupParamImpl;
import org.springframework.util.Assert;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;

import java.util.*;
import java.util.stream.Collectors;

@Getter
@Setter
@NoArgsConstructor
@Accessors(chain = true)
public class EntityModel extends BaseModel {


    private SystemModel system;


    public String getEntityName() {
        return getDataEntity().getName();
    }


    public String getTableName() {
        return StringUtils.isEmpty(getDataEntity().getTableName()) ? getDataEntity().getName() : getDataEntity().getTableName();
    }


    public String getLogicName() {
        return getDataEntity().getLogicName();
    }

    public String getModule() {
        if (getDataEntity().getPSSystemModule() != null)
            return getDataEntity().getPSSystemModule().getCodeName().toLowerCase();
        return "ungroup";
    }


    public IPSDataEntity getDataEntity() {
        return (IPSDataEntity) opt;
    }

    private List<DataSetModel> queries;

    public EntityModel addQueries(DataSetModel dataSet) {
        if (queries == null)
            queries = new ArrayList<>();
        queries.add(dataSet);
        return this;
    }

    private Map<String, DataSetModel> dataQueries;

    public EntityModel addDataQueries(DataSetModel dataSet) {
        if (dataQueries == null)
            dataQueries = new LinkedHashMap<>();
        dataQueries.put(dataSet.getDatasetId(), dataSet);
        if ("View".equalsIgnoreCase(dataSet.codeName) && viewDataQuery == null)
            viewDataQuery = dataSet;
        if (getDataEntity().getDefaultPSDEDataSet().getCodeName().equalsIgnoreCase(dataSet.codeName) && defaultDataQuery == null)
            defaultDataQuery = dataSet;
        return this;
    }

    private DataSetModel viewDataQuery;

    private DataSetModel defaultDataQuery;

    private List<DataSetModel> dataSets;

    public EntityModel addDataSet(DataSetModel dataSet) {
        if (dataSets == null)
            dataSets = new ArrayList<>();
        dataSets.add(dataSet);
        return this;
    }


    private List<FieldModel> fields;

    public EntityModel addField(FieldModel fieldModel) {
        if (fields == null)
            fields = new ArrayList<>();
        fields.add(fieldModel);
        return this;
    }

    private List<RelationshipModel> references;

    public EntityModel addReference(RelationshipModel relationshipModel) {
        if (references == null)
            references = new ArrayList<>();
        references.add(relationshipModel);
        return this;
    }

    public boolean isHasReferences() {
        return !ObjectUtils.isEmpty(references);
    }

    public boolean hasPhisicalLinkField = false;

    private Map<String, RelationshipModel> refMaps;


    public Map<String, RelationshipModel> getRefMaps() {
        if (refMaps == null)
            refMaps = new LinkedHashMap<>();
        if (references != null) {
            references.forEach(ship -> {
                if (!StringUtils.isEmpty(ship.getCodeName()))
                    refMaps.put(ship.getCodeName().toString(), ship);
                String fkname = DataObject.getStringValue(ship.getName(), "");
                if (!StringUtils.isEmpty(fkname))
                    refMaps.put(fkname, ship);
            });
        }
        return refMaps;
    }

    private List<RelationshipModel> nesteds;

    public EntityModel addNested(RelationshipModel relationshipModel) {
        if (nesteds == null)
            nesteds = new ArrayList<>();
        nesteds.add(relationshipModel);
        return this;
    }

    private Map<String, EntityModel> relEntitiesMap;

    public EntityModel addRelEntity(String codeName, EntityModel entityModel) {
        if (entityModel == null || StringUtils.isEmpty(codeName) || codeName.equalsIgnoreCase(this.codeName))
            return this;
        if (relEntitiesMap == null)
            relEntitiesMap = new LinkedHashMap<>();
        relEntitiesMap.put(codeName, entityModel);
        return this;
    }

    public Collection<EntityModel> getRelEntities() {
        if (relEntitiesMap == null) {
            if (this.references != null)
                references.forEach(item -> {
                    this.addRelEntity(item.getEntityCodeName(), item.getRelEntity());
                });
            if (this.nesteds != null)
                nesteds.forEach(item -> {
                    this.addRelEntity(item.getEntityCodeName(), item.getRelEntity());
                });
            if (this.indexRelation != null)
                this.addRelEntity(this.indexRelation.getEntityCodeName(), this.indexRelation.getRelEntity());
        }
        if (relEntitiesMap != null)
            return relEntitiesMap.values();
        return new ArrayList<>();
    }

    private Map<String, FieldModel> fieldMap = null;


    public Map<String, FieldModel> getFieldMap() {
        if (fields != null && fieldMap == null) {
            fieldMap = new LinkedHashMap<>();
            fields.forEach(field -> {
                fieldMap.put(field.getFieldName(), field);
                fieldMap.put(field.getCodeName().toString(), field);
            });
        }
        return fieldMap;
    }


    private FieldModel lastModifyField;


    public FieldModel getLastModifyField() {
        if (fields != null && lastModifyField == null)
            for (FieldModel fieldModel : fields)
                if (fieldModel.isLastModifyField()) {
                    lastModifyField = fieldModel;
                    return lastModifyField;
                }
        return lastModifyField;
    }

    private FieldModel orgField;

    private FieldModel majorField;


    public FieldModel getOrgField() {
        if (fields != null && orgField == null)
            for (FieldModel fieldModel : fields)
                if (fieldModel.isOrgField()) {
                    orgField = fieldModel;
                    return orgField;
                }
        return orgField;
    }


    public boolean isLogicValid() {
        return getDataEntity().isLogicValid();
    }


    private FieldModel logicValidField;


    public FieldModel getLogicValidField() {
        if (isLogicValid() && logicValidField == null) {
            if (fields != null) {
                for (FieldModel fieldModel : fields) {
                    if (fieldModel.isLogicValidField()) {
                        logicValidField = fieldModel;
                        return logicValidField;
                    }
                }
            }
        }
        return logicValidField;
    }


    public String getValidLogicValue() {
        String validLogicValue = this.getDataEntity().getValidLogicValue();
        if (StringUtils.isEmpty(validLogicValue))
            validLogicValue = "1";
        return validLogicValue;
    }


    public String getInvalidLogicValue() {
        String invalidLogicValue = this.getDataEntity().getInvalidLogicValue();
        if (StringUtils.isEmpty(invalidLogicValue))
            invalidLogicValue = "0";
        return invalidLogicValue;
    }


    private FieldModel keyField;


    public FieldModel getKeyField() {
        if (fields != null && keyField == null) {
            for (FieldModel fieldModel : fields) {
                if (fieldModel.isKeyDEField()) {
                    keyField = fieldModel;
                    break;
                }
            }
            if ((!keyField.isPhisicalDEField()) && getUnionKeyFields().size() == 1) {
                keyField = unionKeyFields.get(0);
            }
        }
        return keyField;
    }


    private List<FieldModel> unionKeyFields;


    public List<FieldModel> getUnionKeyFields() {
        if (fields != null && unionKeyFields == null) {
            unionKeyFields = new ArrayList<>();
            if (getDataEntity().getUnionKeyValuePSDEFields() != null) {
                getDataEntity().getUnionKeyValuePSDEFields().forEach(def -> {
                    unionKeyFields.add(getFieldMap().get(def.getCodeName()));
                });
            }
        }
        return unionKeyFields;
    }

    public boolean isUnionKeyMode() {
        return !ObjectUtils.isEmpty(getUnionKeyFields());
    }

    public List<FieldModel> getKeyFields() {
        if (this.getKeyField() != null && this.getKeyField().isPhisicalDEField()) {
            List<FieldModel> keyFields = new ArrayList<>();
            keyFields.add(getKeyField());
            return keyFields;
        } else
            return getUnionKeyFields();
    }

    public List<FieldModel> getQuickSearchFields() {
        return fields.stream().filter(s -> s.getDataEntityField().isEnableQuickSearch()).collect(Collectors.toList());
    }


    private Map<String, ActionModel> actions;

    public EntityModel addAction(ActionModel action) {
        if (actions == null)
            actions = new LinkedHashMap<>();
        actions.put(StringAdvUtils.camelcase(action.getCodeName()), action);
        return this;
    }

    private static Set<String> ignoActions = new HashSet<String>() {{
        add("get");
        add("create");
        add("update");
        add("remove");
        add("save");
        add("getdraft");
        add("checkkey");
        add("createbatch");
        add("savebatch");
        add("updatebatch");
        add("removebatch");
    }};

    public List<ActionModel> getExtActions() {
        return actions.values().stream().filter(s -> !ignoActions.contains(s.getCodeName().toLowerCase())).collect(Collectors.toList());
    }

    public String getDsName() {
        String dsName = this.getDataEntity().getDSLink();
        if (StringUtils.isEmpty(dsName) || "DEFAULT".equalsIgnoreCase(dsName))
            dsName = null;
        else
            dsName = dsName.toLowerCase();
        return dsName;
    }


    public String getTableName(String dsType) {
        return this.getStringValue("table-" + dsType.toLowerCase(), getTableName());
    }


    private String storage = "SQL";

    public void setStorage(Integer type) {
        switch (type) {
            case 0:
                this.storage = "NONE";
                break;
            case 1:
                this.storage = "SQL";
                break;
            case 2:
                this.storage = "NoSQL";
                break;
            case 4:
                this.storage = "ServiceAPI";
                break;
            default:
                this.storage = "SQL";
                break;
        }
    }

    public void setStorage(String type) {
        this.storage = type;
    }


    private RelationshipModel indexRelation;

    public boolean isIndexSubDE() {
        if (this.getIndexRelation() != null)
            return true;
        return false;
    }

    public boolean isLogicInherit() {
        if (this.getIndexRelation() == null)
            return false;
        IPSDERBase MinorPSDER = this.getIndexRelation().getDer();
        if ("DERINHERIT".equals(MinorPSDER.getDERType()) && MinorPSDER instanceof IPSDERInherit) {
            return ((IPSDERInherit) MinorPSDER).isLogicInherit();
        }
        return false;
    }


    public boolean isHasPSDERsMapping() {
        if (this.getReferences() != null) {
            for (RelationshipModel rel : this.getReferences()) {

                if (rel.getRelEntity().getStorage().equals("NONE"))
                    continue;
                if (!(rel.getDer() instanceof PSDER1NImpl))
                    continue;
                if (((PSDER1NImpl) rel.getDer()).getPSDER1NDEFieldMaps() == null)
                    continue;
                for (IPSDER1NDEFieldMap derField : ((PSDER1NImpl) rel.getDer()).getPSDER1NDEFieldMaps()) {
                    if (derField.getMapType().equals("COUNT") || derField.getMapType().equals("SUM")
                            || derField.getMapType().equals("AVG") || derField.getMapType().equals("MAX") || derField.getMapType().equals("MIN"))
                        return true;
                }
            }
        }
        return false;
    }

    public boolean isEnableES() {
        return "elasticsearch".equalsIgnoreCase(this.getDataEntity().getUserTag());
    }

    public boolean isHasDupCheck() {
        if (this.getDefaultDataQuery() == null)
            return false;
        if (getDataEntity().getStorageMode() != 1 && getDataEntity().getStorageMode() != 2)
            return false;
        for (IPSDEField field : getDataEntity().getAllPSDEFields()) {
            if ("ALL".equalsIgnoreCase(field.getDupCheckMode()))
                return true;
        }
        return false;
    }

    public boolean isNeedTypeHandler() {
        if (!"NONE".equalsIgnoreCase(getStorage()))
            return false;
        if (isHasReferences()) {
            for (RelationshipModel ref : getReferences()) {
                if (ref.getDer() instanceof IPSDER1N && ref.getRelEntity().getStorage().equalsIgnoreCase("SQL")) {
                    IPSDEField def = ((IPSDER1N) ref.getDer()).getPSOne2ManyDataDEField();
                    if (def != null && def.isPhisicalDEField())
                        return true;
                }
            }
        }
        return false;
    }

    public List getMqPublishers() {
        List publishers = new ArrayList();
        if (getDataEntity().getAllPSDEDataSyncs() != null) {
            getDataEntity().getAllPSDEDataSyncs().forEach(dataSync -> {
                if (dataSync.getOutPSSysDataSyncAgent() != null && dataSync.getEventType() != 0) {
                    Map map = new HashMap();
                    map.put("dataSync", dataSync);
                    Set<String> monitors = new LinkedHashSet<>();
                    map.put("monitors", monitors);
                    if ((dataSync.getEventType() & 1) > 0)
                        monitors.add("create");
                    if ((dataSync.getEventType() & 2) > 0)
                        monitors.add("update");
                    if ((dataSync.getEventType() & 4) > 0)
                        monitors.add("remove");
                    publishers.add(map);
                }
            });
        }
        return publishers;
    }

    private List<OptionItem> dataScopes;

    public List<OptionItem> getDataScopes() {
        if (dataScopes == null) {
            dataScopes = new ArrayList<>();
            dataScopes.add(new OptionItem().setId("all").setName("全部数据"));
            boolean hasOrgId = false, hasDetpId = false, hasCreateBy = false;
            for (FieldModel field : getFields()) {
                if ("ORGID".equalsIgnoreCase(field.getDataEntityField().getPredefinedType()))
                    hasOrgId = true;
                else if ("ORGSECTORID".equalsIgnoreCase(field.getDataEntityField().getPredefinedType()))
                    hasDetpId = true;
                else if ("CREATEMAN".equalsIgnoreCase(field.getDataEntityField().getPredefinedType()))
                    hasCreateBy = true;
            }
            if (hasOrgId) {
                dataScopes.add(new OptionItem().setId("curorg").setName("当前单位"));
                dataScopes.add(new OptionItem().setId("porg").setName("上级单位"));
                dataScopes.add(new OptionItem().setId("sorg").setName("下级单位"));
            }
            if (hasDetpId) {
                dataScopes.add(new OptionItem().setId("curorgdept").setName("当前部门"));
                dataScopes.add(new OptionItem().setId("porgdept").setName("上级部门"));
                dataScopes.add(new OptionItem().setId("sorgdept").setName("下级部门"));
            }
            if (hasCreateBy)
                dataScopes.add(new OptionItem().setId("createman").setName("创建人"));
        }
        return dataScopes;
    }

    public boolean isHasScopes() {
        return getDataScopes().size() > 1;
    }

    private Map<String, POSchema> poSchemas;

    public POSchema getDefaultPOSchema() {
        return getPOSchema("default");
    }

    public EntityModel addPOSchema(String name, POSchema poSchema) {
        if (poSchema != null) {
            if (poSchemas == null)
                poSchemas = new LinkedHashMap<>();
            poSchemas.put(name, poSchema.build());
        }

        return this;
    }

    public POSchema getPOSchema(String name) {

        if (StringUtils.isEmpty(name) && (!StringUtils.isEmpty(this.getDsName())))
            name = this.getDsName();
        if (StringUtils.isEmpty(name))
            name = "mysql";

        if (poSchemas == null)
            poSchemas = new LinkedHashMap<>();
        if (poSchemas.containsKey(name)) {
            return poSchemas.get(name);
        }
        String vendorProvider = POSchema.provider.get(name.toLowerCase());
        if ((!StringUtils.isEmpty(vendorProvider)) && (!name.equalsIgnoreCase(vendorProvider)) && poSchemas.containsKey(vendorProvider))
            return poSchemas.get(vendorProvider);

        if (poSchemas.size() > 0)
            return poSchemas.values().iterator().next();

        return null;
    }


    public String getStringValue(String key, String defaultVal) {
        return extParams.getStringValue(key, defaultVal);
    }

    private boolean hasResetField = false;

    private ClientEntityModel clientEntityModel;

    public EntityModel(SystemModel systemModel, IPSDataEntity dataEntity) {
        Assert.notNull(dataEntity, "未找到对应的实体模型:" + dataEntity.getId());
        this.opt = dataEntity;
        this.system = systemModel;
        this.setCodeName(dataEntity.getCodeName());
        this.setName(dataEntity.getName());
        this.setStorage(dataEntity.getStorageMode());
        List<String> dsTypes = new ArrayList<>();

        if (dataEntity.getAllPSDEDBConfigs() != null) {
            dataEntity.getAllPSDEDBConfigs().forEach(item -> {
                String dbType = item.getDBType().toLowerCase().replace("mysql5", "mysql");
                if ("mysql".equals(dbType))
                    system.setEnableMysql(true);
                else if ("oracle".equals(dbType))
                    system.setEnableOracle(true);
                else if ("postgresql".equals(dbType))
                    system.setEnablePostgreSQL(true);
                else if ("dameng".equals(dbType) || "dm".equals(dbType))
                    system.setEnableDameng(true);
                dsTypes.add(dbType);
                if (this.getTableName() != null && (!this.getTableName().equalsIgnoreCase(item.getTableName())))
                    this.set("table-" + item.getDBType().toLowerCase().replace("mysql5", "mysql"), item.getTableName());
            });
        }


        if (dataEntity.getMinorPSDERs() != null) {
            for (IPSDERBase der : dataEntity.getMinorPSDERs()) {
                RelationshipModel rel = new RelationshipModel(this, der);
                rel.setRelationType("reference").setCodeName(der.getCodeName()).setEntityId(der.getMajorPSDataEntity().getId())
                        .setEntityCodeName(der.getMajorPSDataEntity().getCodeName()).setEntityName(der.getMajorPSDataEntity().getName())
                        .setEntityLogicName(der.getMajorPSDataEntity().getLogicName()).setTableName(der.getMajorPSDataEntity().getTableName());
                if (der.getMajorPSDataEntity().getPSSystemModule() != null)
                    rel.setModule(der.getMajorPSDataEntity().getPSSystemModule().getCodeName().toLowerCase());


                if (der instanceof IPSDER1N) {
                    IPSDER1N der1n = (IPSDER1N) der;
                    String refFieldName = der1n.getPSPickupDEField().getObjectNode().get("getRelatedPSDEField").get("name").asText();
                    String refCodeName = refFieldName;
                    if (der1n.getPSPickupDEField().getObjectNode().get("getRelatedPSDEField").get("codeName") != null)
                        refCodeName = der1n.getPSPickupDEField().getObjectNode().get("getRelatedPSDEField").get("codeName").asText();

                    LookupModel lookupModel = new LookupModel().setRelationid(der.getId())
                            .setFieldname(der1n.getPickupDEFName()).setCodeName(der1n.getPSPickupDEField().getCodeName()).setReffieldname(refFieldName).setRefCodeName(refCodeName);
                    rel.addLookup(lookupModel);
                } else if (der instanceof IPSDERIndex || der instanceof IPSDERInherit) {
                    if (der.getMajorPSDataEntity().getKeyPSDEField() != null) {
                        LookupModel lookupModel = new LookupModel().setRelationid(der.getId())
                                .setFieldname(this.getDataEntity().getKeyPSDEField().getName()).setCodeName(this.getDataEntity().getKeyPSDEField().getCodeName())
                                .setReffieldname(der.getMajorPSDataEntity().getKeyPSDEField().getName()).setRefCodeName(der.getMajorPSDataEntity().getKeyPSDEField().getCodeName());
                        rel.addLookup(lookupModel);
                    }
                    if (der.getMajorPSDataEntity().getMajorPSDEField() != null) {
                        LookupModel lookupModel = new LookupModel().setRelationid(der.getId())
                                .setFieldname(this.getDataEntity().getMajorPSDEField().getName()).setCodeName(this.getDataEntity().getMajorPSDEField().getCodeName())
                                .setReffieldname(der.getMajorPSDataEntity().getMajorPSDEField().getName()).setRefCodeName(der.getMajorPSDataEntity().getMajorPSDEField().getCodeName());
                        rel.addLookup(lookupModel);
                    }
                    List<IPSDERIndexDEFieldMap> map = ((IPSDERIndex) der).getPSDERIndexDEFieldMaps();
                    if (!ObjectUtils.isEmpty(map)) {
                        map.forEach(item -> {
                            LookupModel lookupModel = new LookupModel().setRelationid(der.getId())
                                    .setFieldname(item.getMinorPSDEField().getName()).setCodeName(item.getMinorPSDEField().getCodeName())
                                    .setReffieldname(item.getMajorPSDEField().getName()).setRefCodeName(item.getMajorPSDEField().getCodeName());
                            rel.addLookup(lookupModel);
                        });
                    }
                }
                //聚合关系 暂时忽略
                else if (der instanceof IPSDERAggData) {
                    continue;
                }

                if ("DERINHERIT".equals(der.getDERType())) {
                    rel.setRelationType("inherit");
                    this.setIndexRelation(rel);
                } else if ("DERINDEX".equals(der.getDERType())//&& der.getMajorPSDataEntity().getVirtualMode()!=3
                        && der.getMajorPSDataEntity().getIndexTypePSDEField() != null) {
                    rel.setRelationType("index");
                    this.setIndexRelation(rel);
                } else {
                    rel.setRelationType("reference");
                    this.addReference(rel);
                }
            }

        }

        if (dataEntity.getMajorPSDERs() != null) {
            for (IPSDERBase der : dataEntity.getMajorPSDERs()) {
                if (der instanceof IPSDER1N) {
                    IPSDER1N der1n = (IPSDER1N) der;
                    String codeName = der.getMinorCodeName();
                    boolean nestedRS = false;
                    if (der1n.isNestedRS())
                        nestedRS = true;
                    else if (der1n.getPSOne2ManyDataDEField() != null) {
                        nestedRS = true;
                    } else if (der1n.getMinorPSDataEntity().getPSSubSysServiceAPIDE() != null && der1n.getMinorPSDataEntity().getPSSubSysServiceAPIDE().isNested()) {
                        nestedRS = true;
                    }
                    if (!nestedRS)
                        continue;

                    if (StringUtils.isEmpty(codeName))
                        codeName = der.getMinorPSDataEntity().getCodeName();

                    RelationshipModel rel = new RelationshipModel(this, der);
                    rel.setRelationType("nested").setCodeName(codeName).setEntityId(der.getMinorPSDataEntity().getId())
                            .setEntityCodeName(der.getMinorPSDataEntity().getCodeName()).setEntityName(der.getMinorPSDataEntity().getName())
                            .setEntityLogicName(der.getMinorPSDataEntity().getLogicName()).setTableName(der.getMinorPSDataEntity().getTableName());

                    if (der.getMinorPSDataEntity().getPSSystemModule() != null)
                        rel.setModule(der.getMinorPSDataEntity().getPSSystemModule().getCodeName().toLowerCase());

                    if (der1n.getPSOne2ManyDataDEField() != null && der1n.getPSOne2ManyDataDEField().isPhisicalDEField() && der1n.getMinorPSDataEntity().getStorageMode() == 0) {
                        rel.setColumnName(der1n.getPSOne2ManyDataDEField().getName().toLowerCase());
                        rel.setCodeName(der1n.getPSOne2ManyDataDEField().getCodeName());
                    }

                    rel.setFkFieldCodeName(der1n.getPSPickupDEField().getCodeName());
                    String refFieldName = der1n.getPSPickupDEField().getObjectNode().get("getRelatedPSDEField").get("name").asText();
                    String refCodeName = refFieldName;
                    if (der1n.getPSPickupDEField().getObjectNode().get("getRelatedPSDEField").get("codeName") != null)
                        refCodeName = der1n.getPSPickupDEField().getObjectNode().get("getRelatedPSDEField").get("codeName").asText();

                    LookupModel lookupModel = new LookupModel().setRelationid(der.getId())
                            .setFieldname(der1n.getPickupDEFName()).setCodeName(der1n.getPSPickupDEField().getCodeName()).setReffieldname(refFieldName).setRefCodeName(refCodeName);
                    rel.addLookup(lookupModel);

                    this.addNested(rel);
                }


            }
        }

        Map<String, FieldModel> fieldMaps = new LinkedHashMap<>();
        for (IPSDEField defield : dataEntity.getAllPSDEFields()) {


            if (defield.isPasteReset())
                this.hasResetField = true;

            FieldModel fieldModel = new FieldModel(this, defield);

            if (defield.isMajorDEField())
                this.majorField = fieldModel;

            try {
                fieldModel.setDict(defield.getPSCodeList() != null ? defield.getPSCodeList().getCodeName() : null);
            } catch (Exception ex) {
            }

            if (defield.getAllPSDEFDTColumns() != null) {
                defield.getAllPSDEFDTColumns().forEach(col -> {
                    if (!fieldModel.getFieldName().equalsIgnoreCase(col.getColumnName()))
                        fieldModel.set("column-" + col.getDBType().toLowerCase().replace("mysql5", "mysql"), col.getColumnName());
                    if (StringUtils.isEmpty(fieldModel) && defield.isFormulaDEField() && (!StringUtils.isEmpty(col.getQueryCodeExp())))
                        fieldModel.setExpression(col.getQueryCodeExp().replace("`", "").replace("[", "").replace("]", ""));
                });
            }

            if (defield.isLinkDEField() && defield instanceof IPSLinkDEField) {
                IPSLinkDEField linkDEField = (IPSLinkDEField) defield;
                String relfieldname = linkDEField.getObjectNode().get("getRelatedPSDEField").get("name").asText();
                String relfieldcodename = linkDEField.getObjectNode().get("getRelatedPSDEField").get("codeName").asText();
                linkDEField.getRelatedPSDEField();
                fieldModel.setRefFieldName(relfieldname).setRefFieldCodeName(relfieldcodename);

                if (!StringUtils.isEmpty(linkDEField.getPSDER().getCodeName())) {
                    RelationshipModel relationshipModel = this.getRefMaps().get(linkDEField.getPSDER().getCodeName());
                    if (relationshipModel != null && (!StringUtils.isEmpty(relationshipModel.getCodeName()))) {
                        relationshipModel.addField(fieldModel);
                        fieldModel.setReference(relationshipModel);
                        if ("PICKUP".equalsIgnoreCase(defield.getDataType())) {
                            relationshipModel.setFkField(fieldModel);
                            relationshipModel.setFkFieldCodeName(fieldModel.getCodeName().toString());
                        } else if (defield.isPhisicalDEField() || (!StringUtils.isEmpty(defield.getUnionKeyValue()))) {
                            hasPhisicalLinkField = true;
                        }
                    }
                }

            }


            fieldMaps.put(fieldModel.getFieldName(), fieldModel);
            this.addField(fieldModel);
        }


        if (dataEntity.getAllPSDEDataQueries() != null) {
            dataEntity.getAllPSDEDataQueries().forEach(dataQuery -> {

                try {
                    if (dataQuery.getAllPSDEDataQueryCodes() != null) {
                        dataQuery.getAllPSDEDataQueryCodes().forEach(dq -> {
                            if (StringUtils.isEmpty(dq.getQueryCode()))
                                return;
                            String select = TransUtils.contextParamConvert(dq.getQueryCode());
                            String where = null;
                            if (dq.getPSDEDataQueryCodeConds() != null) {
                                int i = 0;
                                boolean b = TransUtils.checkIgnoreNullvalueCond(dq.getPSDEDataQueryCodeConds());
                                for (IPSDEDataQueryCodeCond cond : dq.getPSDEDataQueryCodeConds()) {
                                    if (i == 0)
                                        where = " where ";
                                    else if (i > 0)
                                        where = where.concat(" and ");

                                    where = where.concat(b ? TransUtils.checkNullContextParamConvert(cond.getCustomCond()) : TransUtils.contextParamConvert(cond.getCustomCond()));
                                    i++;
                                }
                            }

                            DataSetModel dsModel = new DataSetModel();
                            dsModel.setEntity(this);
                            dsModel.setName(dataQuery.getName());
                            dsModel.setDatasetId(this.getEntityName().toLowerCase() + "-dq-" + dataQuery.getCodeName() + "-" + dq.getDBType().toLowerCase().replace("mysql5", "mysql"))
                                    .setDsType(dq.getDBType().toLowerCase().replace("mysql5", "mysql"))
                                    .setDatasetName(dataQuery.getLogicName()).setCodeName(dataQuery.getCodeName())
                                    .setSelect(select).setWhere(where)
                                    .setDsCode(select.concat(where == null ? "" : where));

                            this.addQueries(dsModel);
                            this.addDataQueries(dsModel);
                        });
                    }
                } catch (Exception exception) {

                }

            });
        }

        if (dataEntity.getAllPSDEDataSets() != null) {
            dataEntity.getAllPSDEDataSets().forEach(dataSet -> {

                String select = "select t1.*";

                String from = " from ( %s ) t1 ";

                String where = null;

                String groupBy = null;

                String orderBy = null;

                if (dataSet.getGroupMode() == 1 || dataSet.getMajorSortPSDEField() != null) {

                    if (dataSet.getGroupMode() == 1 && (!ObjectUtils.isEmpty(dataSet.getPSDEDataSetGroupParams()))) {
                        select = "select ";
                        int i = 0;
                        for (IPSDEDataSetGroupParam obj : dataSet.getPSDEDataSetGroupParams()) {
                            if (!(obj instanceof PSDEDataSetGroupParamImpl))
                                continue;
                            PSDEDataSetGroupParamImpl groupParam = (PSDEDataSetGroupParamImpl) obj;
                            if (i > 0) select = select.concat(",");
                            if (groupParam.isEnableGroup()) {
                                if (!StringUtils.isEmpty(groupParam.getGroupCode()))
                                    select = select.concat(groupParam.getGroupCode());
                                else
                                    select = select.concat(groupParam.getName());
                            } else
                                select = select.concat(groupParam.getGroupCode());
                            select = select.concat(" as ").concat(groupParam.getName().toLowerCase());
                            i++;
                        }
                    }


                    if (dataSet.getGroupMode() == 1 && (!ObjectUtils.isEmpty(dataSet.getPSDEDataSetGroupParams()))) {
                        groupBy = " group by ";
                        int i = 0;
                        for (IPSDEDataSetGroupParam obj : dataSet.getPSDEDataSetGroupParams()) {
                            if (!(obj instanceof PSDEDataSetGroupParamImpl))
                                continue;
                            PSDEDataSetGroupParamImpl groupParam = (PSDEDataSetGroupParamImpl) obj;
                            if (groupParam.isEnableGroup()) {
                                if (i > 0) groupBy = groupBy.concat(",");

                                if (!StringUtils.isEmpty(groupParam.getGroupCode()))
                                    groupBy = groupBy.concat(groupParam.getGroupCode());
                                else
                                    groupBy = groupBy.concat(groupParam.getName());
                                i++;
                            }
                        }
                    }


                }

                try {


                    if (dataSet.getPSDEDataQueries() != null) {
                        DataSetModel dsModel = new DataSetModel(this, dataSet);
                        dsModel.setDatasetId(dataSet.getCodeName())
                                .setDatasetName(dataSet.getLogicName()).setCodeName(dataSet.getCodeName()).setSelect(select).setFrom(from).setGroupBy(groupBy);
                        this.addDataSet(dsModel);

                        Map<String, String> map = new HashMap<>();
                        dataSet.getPSDEDataQueries().forEach(dataQuery -> {

                            try {
                                if (dataQuery.getAllPSDEDataQueryCodes() != null) {
                                    dsModel.addQueries(dataQuery.getCodeName());
                                    dataQuery.getAllPSDEDataQueryCodes().forEach(dq -> {
                                        String code = "";
                                        if (!map.containsKey(dq.getDBType())) {
                                            map.put(dq.getDBType(), "");
                                            code = "";
                                        } else {
                                            code = map.get(dq.getDBType());
                                            code = code + "\r\n union all \r\n";
                                        }
                                        code = code + TransUtils.getQueryCode(dq);
                                        ;//"<include refid=\""+this.getEntityName().toLowerCase()+"_dq_"+dataQuery.getCodeName()+"_"+dq.getDBType().toLowerCase()+"\"/>";
                                        map.put(dq.getDBType(), "select t1.* from (" + code + ") t1");
                                    });
                                }
                            } catch (Exception exception) {

                            }

                        });

                        for (Map.Entry<String, String> entry : map.entrySet()) {
                            if (dataSet.getMajorSortPSDEField() != null) {
                                IPSDEFDTColumn column = dataSet.getMajorSortPSDEField().getPSDEFDTColumn(entry.getKey().toLowerCase().replace("mysql5", "mysql"), false);

                                orderBy = " order by ".concat(column == null ? dataSet.getMajorSortPSDEField().getName() : column.getColumnName());
                                if (!StringUtils.isEmpty(dataSet.getMajorSortDir()))
                                    orderBy = orderBy.concat(" ").concat(dataSet.getMajorSortDir());
                                if (dataSet.getMinorSortPSDEField() != null) {
                                    IPSDEFDTColumn subCol = dataSet.getMinorSortPSDEField().getPSDEFDTColumn(entry.getKey().toLowerCase().replace("mysql5", "mysql"), false);

                                    orderBy = orderBy.concat(",").concat(subCol == null ? dataSet.getMinorSortPSDEField().getName() : subCol.getColumnName());
                                    if (!StringUtils.isEmpty(dataSet.getMinorSortDir()))
                                        orderBy = orderBy.concat(" ").concat(dataSet.getMinorSortDir());

                                }
                            }

                            String sqlFormat = select.concat(from).concat(where == null ? "" : where).concat(groupBy == null ? "" : groupBy).concat(orderBy == null ? "" : orderBy);
                            DataSetModel dqModel = new DataSetModel(this, dataSet);
                            dqModel.setDatasetId(this.getEntityName().toLowerCase() + "-ds-" + dataSet.getCodeName() + "-" + entry.getKey().toLowerCase().replace("mysql5", "mysql"))
                                    .setDsType(entry.getKey().toLowerCase().replace("mysql5", "mysql"))
                                    .setDatasetName(dataSet.getLogicName()).setCodeName(dataSet.getCodeName())
                                    .setDsCode(entry.getValue()).setDsModel(sqlFormat);
                            this.addQueries(dqModel);

                            dsModel.setOrderBy(orderBy).setDsModel(sqlFormat);
                        }


                    }
                } catch (Exception exception) {

                }


            });


        }

        for (String dsType : dsTypes) {
            POSchema poSchema = TransUtils.EntityModelModel2PO(this, dsType);
            if (poSchema != null) {
                this.addPOSchema(dsType, poSchema);
            }
        }


        if (this.getDataEntity().getAllPSDEActions() != null) {
            this.getDataEntity().getAllPSDEActions().forEach(item -> {
                String tag = item.getCodeName().toLowerCase();
                addAction(new ActionModel(this, item));
            });
        }

        //外部接口实体
        if (this.getDataEntity().getPSSubSysServiceAPI() != null && this.getDataEntity().getPSSubSysServiceAPIDE() != null) {
            if (this.getSystem().getClientMap().containsKey(this.getDataEntity().getPSSubSysServiceAPI().getCodeName())) {
                ClientModel clientModel = this.getSystem().getClientMap().get(this.getDataEntity().getPSSubSysServiceAPI().getCodeName());
                if (clientModel.getClientEntityMap().containsKey(this.getDataEntity().getPSSubSysServiceAPIDE().getCodeName())) {
                    clientEntityModel = clientModel.getClientEntityMap().get(this.getDataEntity().getPSSubSysServiceAPIDE().getCodeName());
                }
            }
        }

    }

}
