import { Flo } from '../shared/flo-common';
import * as _ from 'lodash';
const joint = Flo.joint;
import * as _$ from 'jquery';
const $ = _$;
export class Utils {
    static fanRoute(graph, cell) {
        if (cell instanceof joint.dia.Element) {
            const links = graph.getConnectedLinks(cell);
            const groupsOfOverlappingLinks = _.groupBy(links, (link) => {
                // the key of the group is the model id of the link's source or target, but not our cell id.
                const sourceId = link.get('source').id;
                const targetId = link.get('target').id;
                return cell.id !== sourceId ? sourceId : targetId;
            });
            _.each(groupsOfOverlappingLinks, (group, key) => {
                // If the member of the group has both source and target model adjust vertices.
                let toRoute = {};
                if (key !== undefined) {
                    group.forEach((link) => {
                        if (link.get('source').id === cell.get('id') && link.get('target').id) {
                            toRoute[link.get('target').id] = link;
                        }
                        else if (link.get('target').id === cell.get('id') && link.get('source').id) {
                            toRoute[link.get('source').id] = link;
                        }
                    });
                    Object.keys(toRoute).forEach(k => {
                        Utils.fanRoute(graph, toRoute[k]);
                    });
                }
            });
        }
        else if (cell instanceof joint.dia.Link) {
            // The cell is a link. Let's find its source and target models.
            let srcId = cell.get('source').id || cell.previous('source').id;
            let trgId = cell.get('target').id || cell.previous('target').id;
            // If one of the ends is not a model, the link has no siblings.
            if (!srcId || !trgId) {
                return;
            }
            const siblings = graph.getLinks().filter((sibling) => {
                const _srcId = sibling.get('source').id;
                const _trgId = sibling.get('target').id;
                const vertices = sibling.get('vertices');
                const fanRouted = !vertices || vertices.length === 0 || sibling.get('fanRouted');
                return ((_srcId === srcId && _trgId === trgId) || (_srcId === trgId && _trgId === srcId)) && fanRouted;
            });
            switch (siblings.length) {
                case 0:
                    // The link was removed and had no siblings.
                    break;
                case 1:
                    // There is only one link between the source and target. No vertices needed.
                    let vertices = cell.get('vertices');
                    if (vertices && vertices.length && cell.get('fanRouted')) {
                        cell.unset('vertices');
                    }
                    break;
                default:
                    // There is more than one siblings. We need to create vertices.
                    // First of all we'll find the middle point of the link.
                    let source = graph.getCell(srcId);
                    let target = graph.getCell(trgId);
                    if (!source || !target) {
                        // When clearing the graph it may happen that some nodes are gone and some are left
                        return;
                    }
                    let srcCenter = source.getBBox().center();
                    let trgCenter = target.getBBox().center();
                    let midPoint = joint.g.line(srcCenter, trgCenter).midpoint();
                    // Then find the angle it forms.
                    let theta = srcCenter.theta(trgCenter);
                    // This is the maximum distance between links
                    let gap = 20;
                    siblings.forEach((sibling, index) => {
                        // We want the offset values to be calculated as follows 0, 20, 20, 40, 40, 60, 60 ..
                        let offset = gap * Math.ceil(index / 2);
                        // Now we need the vertices to be placed at points which are 'offset' pixels distant
                        // from the first link and forms a perpendicular angle to it. And as index goes up
                        // alternate left and right.
                        //
                        //  ^  odd indexes
                        //  |
                        //  |---->  index 0 line (straight line between a source center and a target center.
                        //  |
                        //  v  even indexes
                        let sign = index % 2 ? 1 : -1;
                        let angle = joint.g.toRad(theta + sign * 90);
                        // We found the vertex.
                        let vertex = joint.g.point.fromPolar(offset, angle, midPoint);
                        sibling.set('fanRouted', true);
                        sibling.set('vertices', [{ x: vertex.x, y: vertex.y }], { 'fanRouted': true });
                    });
            }
        }
    }
    static isCustomPaperEvent(args) {
        return args.length === 5 &&
            _.isString(args[0]) &&
            (args[0].indexOf('link:') === 0 || args[0].indexOf('element:') === 0) &&
            args[1] instanceof $.Event &&
            args[2] instanceof joint.dia.CellView &&
            _.isNumber(args[3]) &&
            _.isNumber(args[4]);
    }
}
//# sourceMappingURL=editor-utils.js.map