
const isNeighbor = function (itemA, itemB) {
    let neighborA = itemA.neighbor,
        neighborB = itemB.neighbor;

    if (neighborA === undefined && neighborB === undefined) {
        return false;
    }

    if (neighborA && neighborA.includes(itemB.id)) {
        return true;
    }

    if (neighborB && neighborB.includes(itemA.id)) {
        return true;
    }

    return false;
}


SV.registerLayout('AdjoinMatrixGraph', {
    sourcesPreprocess(sources) {
        let dataLength = sources.length;
        let matrixNodeLength = dataLength * dataLength;
        let matrixNodes = [];
        let i, j;

        for (i = 0; i < matrixNodeLength; i++) {
            matrixNodes.push({
                id: `mn-${i}`,
                type: 'matrixNode',
                indexTop: i < dataLength ? sources[i].id : undefined,
                indexLeft: i % dataLength === 0?  sources[i / dataLength].id : undefined,
                data: 0
            });
        }

        for (i = 0; i < dataLength; i++) {
            for (j = 0; j < dataLength; j++) {
                let itemI = sources[i],
                    itemJ = sources[j];

                if (itemI.id !== itemJ.id && isNeighbor(itemI, itemJ)) {
                    matrixNodes[i * dataLength + j].data = 1;
                }
            }
        }

        sources.push(...matrixNodes);

        return sources;
    },

    defineOptions() {
        return {
            element: {
                default: {
                    type: 'circle',
                    label: '[id]',
                    size: 40,
                    style: {
                        stroke: '#333',
                        fill: '#95e1d3'
                    }
                },
                matrixNode: {
                    type: 'indexed-node',
                    label: '[data]',
                    size: [40, 40],
                    style: {
                        stroke: '#333',
                        fill: '#95e1d3'
                    },
                    indexOptions: {
                        indexTop: { position: 'top' },
                        indexLeft: { position: 'left' }
                    }
                }
            },
            link: {
                neighbor: {
                    style: {
                        stroke: '#333'
                    }
                }
            },
            layout: {
                radius: 150,
                interval: 250
            },
            behavior: {
                dragNode: ['default']
            }
        };
    },

    layout(elements, layoutOptions) {
        let nodes = elements.filter(item => item.type === 'default'),
            matrixNodes = elements.filter(item => item.type === 'matrixNode'),
            nodeLength = nodes.length,
            matrixNodeLength = matrixNodes.length,
            { interval, radius } = layoutOptions,
            intervalAngle = 2 * Math.PI / nodes.length,
            matrixNodeSize = matrixNodes[0].get('size')[0],
            i;

        const matrixY = -radius,
              matrixX = interval;

        for (i = 0; i < nodeLength; i++) {
            let [x, y] = Vector.rotation(-intervalAngle * i, [0, -radius]);

            nodes[i].set({ x, y });
        }

        for (i = 0; i < matrixNodeLength; i++) {
            let x = matrixX + (i % nodeLength) * matrixNodeSize;
                y = matrixY + Math.floor(i / nodeLength) * matrixNodeSize;

            matrixNodes[i].set({ x, y });
        }
    }
});



