import * as d3 from 'd3';
import { t } from '../../util/locale';
import { geoSphericalDistance } from '../../geo';


export function pointBox(loc, context) {
    var rect = context.surfaceRect();
    var point = context.curtainProjection(loc);
    return {
        left: point[0] + rect.left - 40,
        top: point[1] + rect.top - 60,
        width: 80,
        height: 90
    };
}


export function pad(locOrBox, padding, context) {
    var box;
    if (locOrBox instanceof Array) {
        var rect = context.surfaceRect();
        var point = context.curtainProjection(locOrBox);
        box = {
            left: point[0] + rect.left,
            top: point[1] + rect.top
        };
    } else {
        box = locOrBox;
    }

    return {
        left: box.left - padding,
        top: box.top - padding,
        width: (box.width || 0) + 2 * padding,
        height: (box.width || 0) + 2 * padding
    };
}


export function icon(name, svgklass) {
    return '<svg class="icon ' + (svgklass || '') + '">' +
         '<use xlink:href="' + name + '"></use></svg>';
}


function slugify(text) {
    return text.toString().toLowerCase()
        .replace(/\s+/g, '-')           // Replace spaces with -
        .replace(/[^\w\-]+/g, '')       // Remove all non-word chars
        .replace(/\-\-+/g, '-')         // Replace multiple - with single -
        .replace(/^-+/, '')             // Trim - from start of text
        .replace(/-+$/, '');            // Trim - from end of text
}


// console warning for missing walkthrough names
export var missingStrings = {};
function checkKey(key, text) {
    if (t(key, { default: undefined}) === undefined) {
        if (missingStrings.hasOwnProperty(key)) return;  // warn once
        missingStrings[key] = text;
        var missing = key + ': ' + text;
        if (typeof console !== 'undefined') console.log(missing); // eslint-disable-line
    }
}


export function localize(obj) {
    var key;

    // Assign name if entity has one..
    var name = obj.tags && obj.tags.name;
    if (name) {
        key = 'intro.graph.name.' + slugify(name);
        obj.tags.name = t(key, { default: name });
        checkKey(key, name);
    }

    // Assign street name if entity has one..
    var street = obj.tags && obj.tags['addr:street'];
    if (street) {
        key = 'intro.graph.name.' + slugify(street);
        obj.tags['addr:street'] = t(key, { default: street });
        checkKey(key, street);

        // Add address details common across walkthrough..
        var addrTags = [
            'block_number', 'city', 'county', 'district', 'hamlet', 'neighbourhood',
            'postcode', 'province', 'quarter', 'state', 'subdistrict', 'suburb'
        ];
        addrTags.forEach(function(k) {
            var key = 'intro.graph.' + k,
                tag = 'addr:' + k,
                val = obj.tags && obj.tags[tag],
                str = t(key, { default: val });

            if (str) {
                if (str.match(/^<.*>$/) !== null) {
                    delete obj.tags[tag];
                } else {
                    obj.tags[tag] = str;
                }
            }
        });
    }

    return obj;
}


// Used to detect squareness.. some duplicataion of code from actionOrthogonalize.
export function isMostlySquare(points) {
    // note: uses 15 here instead of the 12 from actionOrthogonalize because
    // actionOrthogonalize can actually straighten some larger angles as it iterates
    var threshold = 15, // degrees within right or straight
        lowerBound = Math.cos((90 - threshold) * Math.PI / 180),  // near right
        upperBound = Math.cos(threshold * Math.PI / 180),         // near straight
        mag;

    for (var i = 0; i < points.length; i++) {
        mag = Math.abs(normalizedDotProduct(i, points));
        if (mag > lowerBound && mag < upperBound) {
            return false;
        }
    }

    return true;


    function normalizedDotProduct(i, points) {
        var a = points[(i - 1 + points.length) % points.length],
            b = points[i],
            c = points[(i + 1) % points.length],
            p = subtractPoints(a, b),
            q = subtractPoints(c, b);

        p = normalizePoint(p);
        q = normalizePoint(q);

        return p[0] * q[0] + p[1] * q[1];


        function subtractPoints(a, b) {
            return [a[0] - b[0], a[1] - b[1]];
        }

        function normalizePoint(point) {
            var vector = [0, 0];
            var length = Math.sqrt(point[0] * point[0] + point[1] * point[1]);
            if (length !== 0) {
                vector[0] = point[0] / length;
                vector[1] = point[1] / length;
            }
            return vector;
        }
    }
}


export function selectMenuItem(operation) {
    var selector = '.edit-menu .edit-menu-item-' + operation +
        ', .radial-menu .radial-menu-item-' + operation;
    return d3.select(selector);
}


export function transitionTime(point1, point2) {
    var distance = geoSphericalDistance(point1, point2);
    if (distance === 0)
        return 0;
    else if (distance < 80)
        return 500;
    else
        return 1000;
}
