



SV.registerLayout('LinkQueue', {

    defineOptions() {
        return {
            element: { 
                head: {
                    type: 'rect',
                    label: '[label]',
                    size: [60, 40],
                    anchorPoints: [
                        [0.5, 0],
                        [1, 0.5],
                        [0.5, 1],
                        [0, 0.5]
                    ],
                    style: {
                        stroke: '#333',
                        fill: null
                    }
                },
                node: {
                    type: 'link-list-node',
                    label: '[data]',
                    size: [60, 30],
                    style: {
                        stroke: '#333',
                        fill: '#b83b5e'
                    }
                }
            },
            link: {
                front: {
                    type: 'polyline',
                    sourceAnchor: 1,
                    targetAnchor: 5,
                    style: {
                        stroke: '#333',
                        endArrow: {
                            path: G6.Arrow.triangle(8, 6, 0), 
                            fill: '#333'
                        }
                    }
                },
                rear: {
                    type: 'polyline',
                    sourceAnchor: 1,
                    targetAnchor: 5,
                    style: {
                        stroke: '#333',
                        endArrow: {
                            path: G6.Arrow.triangle(8, 6, 0), 
                            fill: '#333'
                        }
                    }
                },
                next: { 
                    type: 'line',
                    sourceAnchor: 2,
                    targetAnchor: 6,
                    style: {
                        stroke: '#333',
                        endArrow: {
                            path: G6.Arrow.triangle(8, 6, 0), 
                            fill: '#333'
                        },
                        startArrow: {
                            path: G6.Arrow.circle(2, -1), 
                            fill: '#333'
                        }
                    }
                }
            },
            marker: {
                external: {
                    type: 'pointer',
                    offset: 8,
                    style: {
                        fill: '#f08a5d'
                    }
                }
            },
            layout: {
                xInterval: 50,
                yInterval: 50
            },
            behavior: {
                dragNode: ['node']
            }
        };
    },

    /**
     * 对子树进行递归布局
     * @param node 
     * @param parent 
     */
    layoutItem(node, prev, layoutOptions) {
        if(!node) {
            return null;
        }

        let width = node.get('size')[0];

        if(prev) {
            node.set('y', prev.get('y'));
            node.set('x', prev.get('x') + layoutOptions.xInterval + width);
        }

        if(node.next) {
            this.layoutItem(node.next, node, layoutOptions);
        }
    },


    layout(elements, layoutOptions) {
        let head = elements.filter(item => item.type === 'head'),
            head1 = head[0],
            head2 = head[1],
            nodes = elements.filter(item => item.type !== 'head'),
            mainRoot = nodes.findIndex(item => item.root && head1.front === item),
            roots = nodes.filter(item => item.root),
            headHeight = head1.get('size')[1],
            nodeHeight = 0,
            x = 0, y = 0;

        if(nodes.length) {
            mainRoot = roots.splice(mainRoot, 1)[0];
            roots.unshift(mainRoot);

            x = -50;
            y = mainRoot.get('y');
            nodeHeight = mainRoot.get('size')[1];

            roots.forEach((item, index) => {
                item.set('y', -index * (nodeHeight + layoutOptions.yInterval));
                this.layoutItem(item, null, layoutOptions);
            });
        }
        
        head1.set({ x, y: y + nodeHeight * 3 });
        head2.set({ x, y: head1.get('y') + headHeight });
    }
});

