import {
    event as d3_event,
    select as d3_select
} from 'd3-selection';

import { geoVecFloor } from '../geo';
import { textDirection } from '../util/locale';
import { uiTooltipHtml } from './tooltipHtml';


export function uiEditMenu(context, operations) {
    var menu;
    var center = [0, 0];
    var offset = [0, 0];
    var tooltip;

    var p = 8;               // top padding
    var m = 4;               // top margin
    var h = 15;              // height of icon
    var vpBottomMargin = 45; // viewport bottom margin
    var vpSideMargin = 35;   // viewport side margin
    var buttonWidth = 44;
    var buttonHeight = (2 * p + h);
    var menuWidth = buttonWidth;
    var menuHeight = (2 * m) + operations.length * buttonHeight;
    var menuSideMargin = 10;
    var tooltipWidth = 200;
    var tooltipHeight = 200;  // a reasonable guess, real height depends on tooltip contents


    var editMenu = function (selection) {
        if (!operations.length) return;

        selection.node().parentNode.focus();

        var isRTL = textDirection === 'rtl';
        var viewport = context.surfaceRect();

        if (!isRTL && (center[0] + menuSideMargin + menuWidth) > (viewport.width - vpSideMargin)) {
            // menu is going left-to-right and near right viewport edge, go left instead
            isRTL = true;
        } else if (isRTL && (center[0] - menuSideMargin - menuWidth) < vpSideMargin) {
            // menu is going right-to-left and near left viewport edge, go right instead
            isRTL = false;
        }

        offset[0] = (isRTL ? -1 * (menuSideMargin + menuWidth) : menuSideMargin);

        if (center[1] + menuHeight > (viewport.height - vpBottomMargin)) {
            // menu is near bottom viewport edge, shift upwards
            offset[1] = -1 * (center[1] + menuHeight - viewport.height + vpBottomMargin);
        }

        var origin = [ center[0] + offset[0], center[1] + offset[1] ];

        menu = selection
            .append('g')
            .attr('class', 'edit-menu')
            .attr('transform', 'translate(' + origin + ')')
            .attr('opacity', 0);

        menu
            .transition()
            .attr('opacity', 1);

        menu
            .append('rect')
            .attr('class', 'edit-menu-background')
            .attr('x', 4)
            .attr('rx', 4)
            .attr('ry', 4)
            .attr('width', menuWidth)
            .attr('height', menuHeight)
            .attr('stroke-linecap', 'round');


        var button = menu.selectAll('.edit-menu-item')
            .data(operations)
            .enter()
            .append('g')
            .attr('class', function (d) { return 'edit-menu-item edit-menu-item-' + d.id; })
            .classed('disabled', function (d) { return d.disabled(); })
            .attr('transform', function (d, i) {
                return 'translate(' + geoVecFloor([
                    0,
                    m + i * buttonHeight
                ]).join(',') + ')';
            });

        button
            .append('rect')
            .attr('x', 4)
            .attr('width', buttonWidth)
            .attr('height', buttonHeight)
            .on('click', click)
            .on('mousedown', mousedown)
            .on('mouseover', mouseover)
            .on('mouseout', mouseout);

        button
            .append('use')
            .attr('width', '20')
            .attr('height', '20')
            .attr('transform', function () { return 'translate(' + [2 * p, 5] + ')'; })
            .attr('xlink:href', function (d) { return '#iD-operation-' + d.id; });

        tooltip = d3_select('#id-container')
            .append('div')
            .attr('class', 'tooltip-inner edit-menu-tooltip');


        function click(operation) {
            d3_event.stopPropagation();
            if (operation.disabled()) return;
            operation();
            editMenu.close();
        }

        function mousedown() {
            d3_event.stopPropagation();  // https://github.com/openstreetmap/iD/issues/1869
        }

        function mouseover(d, i) {
            var tipX, tipY;

            if (!isRTL) {
                tipX = viewport.left + origin[0] + menuSideMargin + menuWidth;
            } else {
                tipX = viewport.left + origin[0] - 4 - tooltipWidth;
            }

            if (tipX + tooltipWidth > viewport.right) {
                // tip is going left-to-right and near right viewport edge, go left instead
                tipX = viewport.left + origin[0] - 4 - tooltipWidth;
            } else if (tipX < viewport.left) {
                // tip is going right-to-left and near left viewport edge, go right instead
                tipX = viewport.left + origin[0] + menuSideMargin + menuWidth;
            }

            tipY = viewport.top + origin[1] + (i * buttonHeight);
            if (tipY + tooltipHeight > viewport.bottom) {
                // tip is near bottom viewport edge, shift upwards
                tipY -= tipY + tooltipHeight - viewport.bottom;
            }

            tooltip
                .style('left', tipX + 'px')
                .style('top', tipY + 'px')
                .style('display', 'block')
                .html(uiTooltipHtml(d.tooltip(), d.keys[0], d.title));
        }

        function mouseout() {
            tooltip.style('display', 'none');
        }
    };


    editMenu.close = function () {
        if (menu) {
            menu
                .style('pointer-events', 'none')
                .transition()
                .attr('opacity', 0)
                .remove();
        }

        if (tooltip) {
            tooltip.remove();
        }
    };


    editMenu.center = function (_) {
        if (!arguments.length) return center;
        center = _;
        return editMenu;
    };


    return editMenu;
}
