package cn.ibizlab.core.lite.extensions.domain;

import cn.ibizlab.core.lite.domain.MetaDataSet;
import cn.ibizlab.core.lite.domain.MetaEntity;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.annotation.JSONField;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import org.springframework.util.StringUtils;

import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

@Getter
@Setter
@NoArgsConstructor
@JsonIgnoreProperties(value = "handler")
public class EntityModel {

    @JsonIgnore
    @JSONField(serialize = false)
    public String getEntityId() {
        return getEntity().getEntityId();
    }

    @JsonIgnore
    @JSONField(serialize = false)
    public String getCodeName() {
        return getEntity().getCodeName();
    }

    @JsonIgnore
    @JSONField(serialize = false)
    public String getEntityName() {
        return getEntity().getEntityName();
    }

    @JsonIgnore
    @JSONField(serialize = false)
    public String getTableName() {
        return getEntity().getTableName();
    }

    @JsonIgnore
    @JSONField(serialize = false)
    public String getLogicName() {
        return getEntity().getLogicName();
    }

    @JsonIgnore
    @JSONField(serialize = false)
    public String getSystemId() {
        return getEntity().getSystemId();
    }

    private MetaEntity entity;

    private List<MetaDataSet> dataSets;

    private List<FieldModel> fields;

    private List<RelationshipModel> references;

    private List<RelationshipModel> nesteds;

    @JsonIgnore
    @JSONField(serialize = false)
    private Map<String,FieldModel> fieldMap = null;

    @JsonIgnore
    @JSONField(serialize = false)
    public Map<String,FieldModel> getFieldMap()
    {
        if(fields!=null&&fieldMap==null)
        {
            fieldMap=new LinkedHashMap<>();
            fields.forEach(field->{
                fieldMap.put(field.getColumnName(),field);
                fieldMap.put(field.getCodeName(),field);
            });
        }
        return fieldMap;
    }

    @JsonIgnore
    @JSONField(serialize = false)
    private FieldModel lastModifyField;
    @JsonIgnore
    @JSONField(serialize = false)
    public FieldModel getLastModifyField() {
        if(fields!=null&&lastModifyField==null)
            for(FieldModel fieldModel:fields)
                if(fieldModel.isLastModifyField())
				{
					lastModifyField=fieldModel;
					return lastModifyField;
				}
        return lastModifyField;
    }

	@JsonIgnore
	@JSONField(serialize = false)
    private boolean isLogicValid=true;
	@JsonIgnore
	@JSONField(serialize = false)
    private FieldModel logicValidField;
	@JsonIgnore
	@JSONField(serialize = false)
	public FieldModel getLogicValidField() {
		if(isLogicValid&&logicValidField==null) {
			if (fields != null) {
				for (FieldModel fieldModel : fields) {
					if (fieldModel.isLogicValidField()) {
						logicValidField = fieldModel;
						return logicValidField;
					}
				}
			}
			isLogicValid = false;
		}
		return logicValidField;
	}

	@JsonIgnore
	@JSONField(serialize = false)
	private String logicVal;
	@JsonIgnore
	@JSONField(serialize = false)
	public String getLogicVal()
	{
		if(StringUtils.isEmpty(logicVal))
		    logicVal=this.getExtParams("logicval");
		if(StringUtils.isEmpty(logicVal))
			logicVal="1";
		return logicVal;
	}
	@JsonIgnore
	@JSONField(serialize = false)
	private String logicDelVal;
	@JsonIgnore
	@JSONField(serialize = false)
	public String getLogicDelVal()
	{
		if(StringUtils.isEmpty(logicVal))
			logicDelVal=this.getExtParams("logicdelval");
		if(StringUtils.isEmpty(logicDelVal))
			logicDelVal="0";
		return logicDelVal;
	}
	@JsonIgnore
	@JSONField(serialize = false)
	private FieldModel keyField;
    @JsonIgnore
    @JSONField(serialize = false)
    public FieldModel getKeyField() {
        if(fields!=null&&keyField==null)
            for(FieldModel fieldModel:fields)
                if(fieldModel.isKeyField()) {
					keyField=fieldModel;
					return keyField;
				}
        return keyField;
    }

	@JsonIgnore
	@JSONField(serialize = false)
    private List<FieldModel> unionKeyFields;
	@JsonIgnore
	@JSONField(serialize = false)
	public List<FieldModel> getUnionKeyFields() {
		if(fields!=null&&unionKeyFields==null) {
			unionKeyFields = new ArrayList<>();
			for (FieldModel fieldModel : fields)
				if (fieldModel.isUnionKeyField())
					unionKeyFields.add(fieldModel);
		}
		return unionKeyFields;
	}

    public FieldModel getField(String name)
    {
        if(StringUtils.isEmpty(name))
            return null;
        if(fields==null)
            return null;
        if(getFieldMap()!=null)
            return getFieldMap().get(name);
        return null;
    }


    public String getSqlSegment(String dataSet)
    {
        if("BASE".equalsIgnoreCase(dataSet))
        {
            String columnSet="";
            for(FieldModel fieldModel:fields)
            {
                String columnExp=fieldModel.getColumnExp();
                if(StringUtils.isEmpty(columnExp))
                    continue;
                if(!StringUtils.isEmpty(columnSet)){
                    columnSet=columnSet+",";
                }
                columnSet=columnSet+columnExp;
            }

            return "select "+columnSet+" from "+this.getTableName()+" t ";
        }
        else if("CORE".equalsIgnoreCase(dataSet))
        {
            String columnSet=this.getKeyField().getColumnExp();
            for(FieldModel fieldModel:this.getUnionKeyFields())
			{
				String columnExp=fieldModel.getColumnExp();
				if(StringUtils.isEmpty(columnExp))
					continue;
				columnSet = columnSet + "," + columnExp;
			}

            return "select "+columnSet+" from "+this.getTableName()+" ";
        }
        else if("COUNT".equalsIgnoreCase(dataSet))
        {
            return "select count(1) from "+this.getTableName()+" ";
        }
        else
        {
            if(dataSets!=null)
                for (MetaDataSet metaDataSet:dataSets)
                    if(metaDataSet.getCodeName().equalsIgnoreCase(dataSet)&&(!StringUtils.isEmpty(metaDataSet.getDsCode())))
                        return "select t1.* from ("+metaDataSet.getDsCode()+") t1";
        }
        return "";
    }

    @JsonIgnore
    @JSONField(serialize = false)
    public String getDsName()
    {
        String dsName=this.getEntity().getDsId();
        if(StringUtils.isEmpty(dsName))
        {
            dsName=this.getSystemId()+"-master";
        }
        return dsName;
    }


    public String getExtParams(String key)
	{
        return Setting.getValue(this.getEntity().getExtParams(),key);
	}


}
