package cn.ibizlab.core.data.domain;

import java.util.*;

import cn.ibizlab.core.data.dto.BaseData;
import cn.ibizlab.core.data.dto.FilterData;
import cn.ibizlab.core.data.model.POSchema;
import cn.ibizlab.core.data.model.PojoSchema;
import cn.ibizlab.core.data.model.TransUtils;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.annotation.JSONField;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonProperty;
import org.springframework.util.DigestUtils;
import org.springframework.util.ObjectUtils;
import cn.ibizlab.util.helper.DataObject;
import java.io.Serializable;
import lombok.*;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import org.springframework.util.StringUtils;


/**
 * [业务实体] 对象
 */
@Builder
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
@ApiModel("业务实体")
public class DOModel implements Serializable {

    /**
     * 标识
     */
    @JSONField(name = "id")
    @JsonProperty("id")
    @ApiModelProperty("标识")
    private String id;

    /**
     * 名称
     */
    @JSONField(name = "name")
    @JsonProperty("name")
    @ApiModelProperty("名称")
    private String name;

    /**
     * 名称
     */
    @JSONField(name = "title")
    @JsonProperty("title")
    @ApiModelProperty("名称")
    private String title;

    /**
     * 系统
     */
    @JSONField(name = "systemId")
    @JsonProperty("systemId")
    @ApiModelProperty("系统")
    private String systemId;

    /**
     * 包名
     */
    @JSONField(name = "packageName")
    @JsonProperty("packageName")
    @ApiModelProperty("包名")
    private String packageName;

    /**
     * 描述
     */
    @JSONField(name = "description")
    @JsonProperty("description")
    @ApiModelProperty("描述")
    private String description;

    /**
     * 定义
     */
    @JSONField(name = "schema")
    @JsonProperty("schema")
    @ApiModelProperty("定义")
    private PojoSchema schema;

    /**
     * 模型
     */
    @JSONField(name = "model")
    @JsonProperty("model")
    @ApiModelProperty("模型")
    private String model;

    public void setSchema(PojoSchema schema) {

        if(schema!=null)
        {
            if(StringUtils.isEmpty(schema.getId()))
                schema.setId(schema.getSystem()+".domain."+schema.getName());
            this.setId(schema.getId());
            if(!StringUtils.isEmpty(schema.getName()))
                this.setName(schema.getName());
            if(!StringUtils.isEmpty(schema.getSystem()))
                this.setSystemId(schema.getSystem());
            if(!StringUtils.isEmpty(schema.getTitle()))
                this.setTitle(schema.getTitle());
            if(!StringUtils.isEmpty(schema.getDescription()))
                this.setDescription(schema.getDescription());
            if(!StringUtils.isEmpty(schema.getPackage()))
                this.setPackageName(schema.getPackage());
        }
        this.schema = schema;
    }

    /**
     * 存储
     */
    @JSONField(name = "poModels")
    @JsonProperty("poModels")
    @ApiModelProperty("存储")
    private String poModels;

    public String getPoModels()
    {
        if(StringUtils.isEmpty(poModels)&&this.poSchemas!=null)
            poModels= JSON.toJSONString(poSchemas);
        return poModels;
    }



    public Serializable getKeyValue(BaseData data,boolean genKeyWhenNotExists)
    {
        if(this.getSchema()!=null) {
            return this.getSchema().getKeyValue(data, genKeyWhenNotExists);
        }
        return null;
    }

    public BaseData newData(Object keyValue)
    {
        if(this.getSchema()!=null)
            return this.getSchema().newData(keyValue);
        return null;
    }

    public DOModel fillParentKey(BaseData data)
    {
        if(this.getSchema()!=null)
            this.getSchema().fillParentKey(data);
        return this;
    }

    public DOModel fillParentFilter(FilterData data)
    {
        if(this.getSchema()!=null)
            this.getSchema().fillParentFilter(data);
        return this;
    }

    public DOModel fillDefaultValue(BaseData data,boolean newFlag)
    {
        if(this.getSchema()!=null)
            this.getSchema().fillDefaultValue(data,newFlag);
        return this;
    }



	@JSONField(serialize = false)
	@JsonIgnore
	public String getDefaultDataSource()
	{
		return getSchema()!=null?getSchema().getDefaultDataSoruce():"";
	}


    @JSONField(serialize = false)
    @JsonIgnore
	private Map<String,POSchema> poSchemas;

    @JSONField(serialize = false)
    @JsonIgnore
    public POSchema getDefaultPOSchema()
    {
        return getPOSchema("default");
    }
    public DOModel 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)&&this.getSchema()!=null&&(!StringUtils.isEmpty(this.getSchema().getDefaultDataSoruce())))
            name=this.getSchema().getDefaultDataSoruce();
        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(this.getSchema()!=null&&("mongodb".equals(name)))
        {
            POSchema documentPOSchema= TransUtils.PojoSchema2DocumentPO(this.getSchema());
            if(documentPOSchema!=null) {
                poSchemas.put(name, documentPOSchema);
                return documentPOSchema;
            }
        }

        if(this.getSchema()!=null&&("default".equals(name)||this.getSchema().getDefaultDataSoruce().equalsIgnoreCase(name)))
        {
            POSchema defaultPOSchema= TransUtils.PojoSchema2PO(this.getSchema());
            if(defaultPOSchema!=null) {
                poSchemas.put("default", defaultPOSchema);
                if(!StringUtils.isEmpty(this.getSchema().getDefaultDataSoruce()))
                    poSchemas.put(this.getSchema().getDefaultDataSoruce().toLowerCase(),defaultPOSchema);
                return defaultPOSchema;
            }
        }
        return null;
    }

}


