import { t } from '../core/localizer';
import { validationIssue, validationIssueFix } from '../core/validation';
import { operationSplit } from '../operations/split';

export function validationOsmApiLimits(context) {
    const type = 'osm_api_limits';

    const validation = function checkOsmApiLimits(entity) {
        const issues = [];
        const osm = context.connection();
        if (!osm) return issues; // cannot check if there is no connection to the osm api, e.g. during unit tests
        const maxWayNodes = osm.maxWayNodes();

        if (entity.type === 'way') {
            if (entity.nodes.length > maxWayNodes) {
                issues.push(new validationIssue({
                    type: type,
                    subtype: 'exceededMaxWayNodes',
                    severity: 'error',
                    message: function() {
                        return t.append('issues.osm_api_limits.max_way_nodes.message');
                    },
                    reference: function(selection) {
                        selection.selectAll('.issue-reference')
                            .data([0])
                            .enter()
                            .append('div')
                            .attr('class', 'issue-reference')
                            .call(t.append('issues.osm_api_limits.max_way_nodes.reference', { maxWayNodes }));
                    },
                    entityIds: [entity.id],
                    dynamicFixes: splitWayIntoSmallChunks
                }));
            }
        }

        return issues;
    };

    function splitWayIntoSmallChunks() {
        const fix = new validationIssueFix({
            icon: 'iD-operation-split',
            title: t.append('issues.fix.split_way.title'),
            entityIds: this.entityIds,
            onClick: function(context) {
                const maxWayNodes = context.connection().maxWayNodes();
                const g = context.graph();

                const entityId = this.entityIds[0];
                const entity = context.graph().entities[entityId];
                const numberOfParts = Math.ceil(entity.nodes.length / maxWayNodes);
                let splitVertices;

                if (numberOfParts === 2) {
                    // simple case: try to split at the an intersection vertex
                    const splitIntersections = entity.nodes
                        .map(nid => g.entity(nid))
                        .filter(n => g.parentWays(n).length > 1)
                        .map(n => n.id)
                        .filter(nid => {
                            const splitIndex = entity.nodes.indexOf(nid);
                            return splitIndex < maxWayNodes &&
                                entity.nodes.length - splitIndex < maxWayNodes;
                        });
                    if (splitIntersections.length > 0) {
                        splitVertices = [
                            splitIntersections[Math.floor(splitIntersections.length / 2)]
                        ];
                    }
                }

                if (splitVertices === undefined) {
                    // general case: either more than one split is needed or no possible
                    // intersection split point was found -> just split at regular intervals
                    splitVertices = [...Array(numberOfParts - 1)].map((_, i) =>
                        entity.nodes[Math.floor(entity.nodes.length * (i + 1) / numberOfParts)]);
                }

                if (entity.isClosed()) {
                    // add extra split for closed ways at start of way
                    splitVertices.push(entity.nodes[0]);
                }

                const operation = operationSplit(context, splitVertices.concat(entityId));
                if (!operation.disabled()) {
                    operation();
                }
            }
        });

        return [fix];
    }


    validation.type = type;

    return validation;
}
