package cn.axzo.msg.center.message.service.group;

import cn.axzo.maokai.api.vo.response.tree.Node;
import cn.axzo.maokai.api.vo.response.tree.RootNode;
import cn.axzo.maokai.api.vo.response.tree.ValueNode;
import cn.axzo.msg.center.common.utils.BizAssertions;

import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;

import static java.util.function.Function.identity;
import static java.util.stream.Collectors.toList;
import static java.util.stream.Collectors.toMap;

/**
 * @author yanglin
 */
public class RootNodeWrapper {

    private final Map<String, ValueNode<NodeWrapper>> code2Node;
    private final Map<Long, ValueNode<NodeWrapper>> id2Node;

    RootNodeWrapper(RootNode<NodeWrapper> root) {
        this.code2Node = root.getValueNodes().stream()
                .collect(toMap(node -> node.getValue().getNodeCode(), identity()));
        this.id2Node = root.getValueNodes().stream()
                .collect(toMap(node -> node.getValue().unwrap().getId(), identity()));
    }

    public Optional<ValueNode<NodeWrapper>> findValueNode(String groupNodeCode) {
        return Optional.ofNullable(code2Node.get(groupNodeCode));
    }

    public Optional<ValueNode<NodeWrapper>> findValueNode(Long id) {
        return Optional.ofNullable(id2Node.get(id));
    }

    public List<ValueNode<NodeWrapper>> getNodes(Collection<String> groupNodeCodes) {
        return groupNodeCodes.stream()
                .map(this::findValueNode)
                .map(node -> node.orElse(null))
                .filter(Objects::nonNull)
                .sorted(NodeComparator.INSTANCE)
                .collect(toList());
    }

    public String getPath(ValueNode<NodeWrapper> node) {
        NodeWrapper wrapper = node.getValue();
        if (wrapper.getCachedPath() == null)
            wrapper.setCachedPath(getPathImpl(node));
        return wrapper.getCachedPath();
    }

    private String getPathImpl(ValueNode<NodeWrapper> node) {
        // a1912618861c4dab8aaee954069762a0:a1912618861c4dab8aaee954069762a1:a1912618861c4dab8aaee954069762a2
        // code是uuid去掉-, 一般层级为3, 通过冒号分割, 所有长度为: 32 * 3 + 2 = 98
        // 初始长度直接设置为98, 避免频繁扩容
        StringBuilder builder = new StringBuilder(98);
        Node current = node;
        int stack = 0;
        while (current != null) {
            // Assuming a reasonable maximum depth to avoid frequent resizing
            BizAssertions.assertTrue(stack <= 500, "分类层级过多或者数据错误");
            stack++;
            @SuppressWarnings("unchecked")
            ValueNode<NodeWrapper> valueNode = current.tryCast(ValueNode.class);
            if (valueNode != null) {
                if (builder.length() > 0)
                    builder.insert(0, ":");
                builder.insert(0, valueNode.getValue().getNodeCode());
            }
            current = current.getParent();
        }
        return builder.toString();
    }

}