package cn.ibizlab.codegen.model;


import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.annotation.JSONField;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import lombok.experimental.Accessors;
import net.ibizsys.model.app.IPSApplication;
import net.ibizsys.model.app.codelist.IPSAppCodeList;
import net.ibizsys.model.codelist.IPSCodeItem;
import org.springframework.util.ObjectUtils;

import java.util.*;

@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
@Accessors(chain = true)
public class Catalog extends BaseModel
{
	private String code;
	private String name;

	@JSONField(name = "items")
	@JsonProperty("items")
	private List<Option> options = new ArrayList<>();


	@JsonIgnore
	@JSONField(serialize = false)
	public IPSAppCodeList getCodeList()
	{
		return (IPSAppCodeList)opt;
	}

	public String getValueSeparator()
	{
		return getCodeList().getValueSeparator()==null?";":getCodeList().getValueSeparator();
	}

	public String getTextSeparator()
	{
		return getCodeList().getTextSeparator()==null?";":getCodeList().getTextSeparator();
	}


	@JsonIgnore
	@JSONField(serialize = false)
	public String getValueType()
	{
		return ObjectUtils.isEmpty(options)?"String":options.get(0).getValueType();
	}


	@JsonIgnore
	@JSONField(serialize = false)
	private Map<String,Option> sets;
	@JsonIgnore
	@JSONField(serialize = false)
	public Map<String,Option> getSets() {
		if(sets==null) {
			sets = new LinkedHashMap<>();
			this.getOptions().forEach(opt->loop(opt));
		}
		return sets;
	}
	@JsonIgnore
	@JSONField(serialize = false)
	public Collection getOptionItems()
	{
		if (getSets().size()>1000)
			return options;
		else
			return sets.values();
	}

	private void loop(Option opt) {
		sets.put(opt.getValue().toString(),opt);
		if(!ObjectUtils.isEmpty(opt.getChildren()))
			opt.getChildren().forEach(sub->{
				loop(sub);
			});
	}


	public Option findCodeItem(Object value)
	{
		return findCodeItem(value,this.options);
	}

	public Option findCodeItem(Object value, List<Option> options){
		for(Option codeItem : options){
			if(value != null && codeItem.getValue() != null && value.equals(codeItem.getValue()))
				return codeItem;
			else if (!ObjectUtils.isEmpty(codeItem.getChildren()))
			{
				Option rt=findCodeItem(value,codeItem.getChildren());
				if(rt!=null)
					return rt;
			}
		}
		return null;
	}



	public List<Option> loop(Map<String, List<Option>> listCodeItem, Object parentValue) {
		List<Option> trees = new ArrayList<Option>();
		if(listCodeItem.containsKey(parentValue)) {
			for (Option codeItem : listCodeItem.get(parentValue)) {
				List<Option> childCodeItem = loop(listCodeItem, codeItem.getValue());
				if (childCodeItem.size() > 0)
					codeItem.setChildren(childCodeItem);
				trees.add(codeItem);
			}
		}
		return trees;
	}


	public Catalog setCodeItem(List<IPSCodeItem> items) {
		items.forEach(item->{
			options.add(new Option().setItem(item));
		});
		return this;
	}
}
