import { actionConnect } from './connect';
import { geoVecAdd, geoVecScale } from '../geo';
import type { Action } from '../core/history';
import type { NodeId } from '../osm';
import type { coreGraph } from '../core/graph';
import type { Vec2 } from '../geo/vector';


// `actionMergeNodes` is just a combination of:
//
// 1. move all the nodes to a common location
// 2. `actionConnect` them

export function actionMergeNodes(nodeIDs: NodeId[], loc?: Vec2): Action {

    // If there is a single "interesting" node, use that as the location.
    // Otherwise return the average location of all the nodes.
    function chooseLoc(graph: coreGraph) {
        if (!nodeIDs.length) return null;
        var sum: Vec2 = [0,0];
        var interestingCount = 0;
        var interestingLoc;

        for (var i = 0; i < nodeIDs.length; i++) {
            var node = graph.entity(nodeIDs[i]);
            if (node.hasInterestingTags()) {
                interestingLoc = (++interestingCount === 1) ? node.loc : null;
            }
            sum = geoVecAdd(sum, node.loc);
        }

        return interestingLoc || geoVecScale(sum, 1 / nodeIDs.length);
    }


    const action: Action = function(graph) {
        if (nodeIDs.length < 2) return graph;
        var toLoc = loc;
        if (!toLoc) {
            toLoc = chooseLoc(graph)!;
        }

        for (var i = 0; i < nodeIDs.length; i++) {
            var node = graph.entity(nodeIDs[i]);
            if (node.loc !== toLoc) {
                graph = graph.replace(node.move(toLoc));
            }
        }

        return actionConnect(nodeIDs)(graph);
    };


    action.disabled = function(graph) {
        if (nodeIDs.length < 2) return 'not_eligible';

        for (var i = 0; i < nodeIDs.length; i++) {
            var entity = graph.entity(nodeIDs[i]);
            if (entity.type !== 'node') return 'not_eligible';
        }

        return actionConnect(nodeIDs).disabled!(graph);
    };

    return action;
}
