package cn.ibizlab.core.data.model;

import com.alibaba.fastjson.annotation.JSONField;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonInclude;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import lombok.experimental.Accessors;

import java.util.*;

@Getter
@Setter
@NoArgsConstructor
@Accessors(chain = true)
@JsonInclude(JsonInclude.Include.NON_EMPTY)
@JsonIgnoreProperties(ignoreUnknown = true)
public class PojoModel
{
    @JSONField(ordinal = 0)
    private String ref;
    @JSONField(ordinal = 1)
    private String id;
    @JSONField(ordinal = 2)
    private String code;
    @JSONField(ordinal = 3)
    private String name;
    @JSONField(ordinal = 4)
    private String group;
    @JSONField(ordinal = 5)
    private List<PojoProperty> propertyList;
    @JSONField(ordinal = 6)
    private Map<String, Object> extensions;

    public PojoModel setPropertyList(List<PojoProperty> propertyList) {
        if (propertyList != null)
            propertyList.forEach(property -> property.setOwnerModel(this));
        this.propertyList = propertyList;
        return this;
    }

    public PojoModel addProperty(PojoProperty property) {
        if (propertyList == null)
            propertyList = new ArrayList<>();
        property.setOwnerModel(this);
        this.propertyList.add(property);
        return this;
    }

    @JsonIgnore
    @JSONField(serialize = false)
    private Map<String, PojoProperty> properties;

    @JsonIgnore
    @JSONField(serialize = false)
    public Map<String, PojoProperty> getProperties()
    {
        if(this.getPropertyList()!=null&&properties==null)
        {
            properties = new LinkedHashMap<>();
            getPropertyList().forEach(property->{
                properties.put(property.getCode(),property);
            });
        }
        return properties;
    }


    @JsonIgnore
    @JSONField(serialize = false)
    public Map<String, PojoProperty> getAllProperties()
    {
        Map<String, PojoProperty> list=new LinkedHashMap<>();

        if(getPropertyList()!=null)
        {
            getPropertyList().forEach(item->{
                loop(item,list);
            });
        }
        return list;
    }

    private void loop(PojoProperty property, Map<String, PojoProperty> list)
    {
        list.put(property.getTag(),property);
        if(PropertyType.nested.equals(property.getPropertyType())
                || PropertyType.object.equals(property.getPropertyType()))
        {

            if(property.getModel()!=null&&property.getModel().getPropertyList()!=null)
            {
                property.getModel().getPropertyList().forEach(item->{
                    loop(item, list);
                });
            }
        }
    }

    public PojoProperty getProperty(String code)
    {
        if(code.indexOf(".")>0)
        {
            String arr[]=code.split("[.]");
            if(arr.length>0)
            {
                PojoProperty property=(getProperties()!=null)?properties.get(arr[0]):null;
                if(property==null)
                    return null;
                if(property.getModel()!=null)
                    return property.getModel().getProperty(code.substring(code.indexOf(".")+1));
                else
                    return null;
            }
        }
        return (getProperties()!=null)?properties.get(code):null;
    }




    public static enum PropertyType {
        string("string", "字符"),
        integer("integer", "整型"),
        number("number", "数值"),
        date("date", "日期"),
        datetime("datetime", "时间"),
        object("object", "对象"),
        nested("nested", "嵌套"),
        recursion("recursion", "递归"),
        array("array", "数组");
        public final String code;
        public final String name;

        private PropertyType(String code, String name) {
            this.code = code;
            this.name = name;
        }

        public String getCode() {
            return code;
        }

        public String getName() {
            return name;
        }

        @Override
        public String toString() {
            return "PropertyType{" +
                    "code='" + code + '\'' +
                    ", name='" + name + '\'' +
                    '}';
        }
    }
}
