import { dispatch as d3_dispatch } from 'd3-dispatch';
import { select as d3_select } from 'd3-selection';
import * as countryCoder from '@rapideditor/country-coder';

import { uiCombobox } from '../combobox';
import { t, localizer } from '../../core/localizer';
import { utilGetSetValue, utilNoAuto, utilRebind, utilTotalExtent } from '../../util';
import { likelyRawNumberFormat } from './input';


export function uiFieldRoadheight(field, context) {
    var dispatch = d3_dispatch('change');
    var primaryUnitInput = d3_select(null);
    var primaryInput = d3_select(null);
    var secondaryInput = d3_select(null);
    var secondaryUnitInput = d3_select(null);
    var _entityIDs = [];
    var _tags;
    var _isImperial;
    var formatFloat = localizer.floatFormatter(localizer.languageCode());
    var parseLocaleFloat = localizer.floatParser(localizer.languageCode());

    var primaryUnits = [
        {
            value: 'm',
            title: t('inspector.roadheight.meter'),
        },
        {
            value: 'ft',
            title: t('inspector.roadheight.foot'),
        },
    ];

    var unitCombo = uiCombobox(context, 'roadheight-unit')
        .data(primaryUnits);

    function roadheight(selection) {

        var wrap = selection.selectAll('.form-field-input-wrap')
            .data([0]);

        wrap = wrap.enter()
            .append('div')
            .attr('class', 'form-field-input-wrap form-field-input-' + field.type)
            .merge(wrap);


        primaryInput = wrap.selectAll('input.roadheight-number')
            .data([0]);

        primaryInput = primaryInput.enter()
            .append('input')
            .attr('type', 'text')
            .attr('class', 'roadheight-number')
            .attr('id', field.domId)
            .call(utilNoAuto)
            .merge(primaryInput);

        primaryInput
            .on('change', change)
            .on('blur', change);

        var loc = combinedEntityExtent().center();
        _isImperial = countryCoder.roadHeightUnit(loc) === 'ft';

        primaryUnitInput = wrap.selectAll('input.roadheight-unit')
            .data([0]);

        primaryUnitInput = primaryUnitInput.enter()
            .append('input')
            .attr('type', 'text')
            .attr('class', 'roadheight-unit')
            .call(unitCombo)
            .merge(primaryUnitInput);

        primaryUnitInput
            .on('blur', changeUnits)
            .on('change', changeUnits);

        secondaryInput = wrap.selectAll('input.roadheight-secondary-number')
            .data([0]);

        secondaryInput = secondaryInput.enter()
            .append('input')
            .attr('type', 'text')
            .attr('class', 'roadheight-secondary-number')
            .call(utilNoAuto)
            .merge(secondaryInput);

        secondaryInput
            .on('change', change)
            .on('blur', change);

        secondaryUnitInput = wrap.selectAll('input.roadheight-secondary-unit')
            .data([0]);
        secondaryUnitInput = secondaryUnitInput.enter()
            .append('input')
            .attr('type', 'text')
            .call(utilNoAuto)
            .classed('disabled', true)
            .classed('roadheight-secondary-unit', true)
            .attr('readonly', 'readonly')
            .merge(secondaryUnitInput);


        function changeUnits() {
            var primaryUnit = utilGetSetValue(primaryUnitInput);
            if (primaryUnit === 'm') {
                _isImperial = false;
            } else if (primaryUnit === 'ft') {
                _isImperial = true;
            }
            utilGetSetValue(primaryUnitInput, _isImperial ? 'ft' : 'm');
            setUnitSuggestions();
            change();
        }
    }


    function setUnitSuggestions() {
        utilGetSetValue(primaryUnitInput, _isImperial ? 'ft' : 'm');
    }


    function change() {
        var tag = {};
        var primaryValue = utilGetSetValue(primaryInput).trim();
        var secondaryValue = utilGetSetValue(secondaryInput).trim();

        // don't override multiple values with blank string
        if (!primaryValue && !secondaryValue && Array.isArray(_tags[field.key])) return;

        if (!primaryValue && !secondaryValue) {
            tag[field.key] = undefined;
        } else {
            var rawPrimaryValue = likelyRawNumberFormat.test(primaryValue)
                ? parseFloat(primaryValue)
                : parseLocaleFloat(primaryValue);
            if (isNaN(rawPrimaryValue)) rawPrimaryValue = primaryValue;
            var rawSecondaryValue = likelyRawNumberFormat.test(secondaryValue)
                ? parseFloat(secondaryValue)
                : parseLocaleFloat(secondaryValue);
            if (isNaN(rawSecondaryValue)) rawSecondaryValue = secondaryValue;

            if (isNaN(rawPrimaryValue) || isNaN(rawSecondaryValue) || !_isImperial) {
                tag[field.key] = context.cleanTagValue(rawPrimaryValue);
            } else {
                if (rawPrimaryValue !== '') {
                    rawPrimaryValue = rawPrimaryValue + '\'';
                }
                if (rawSecondaryValue !== '') {
                    rawSecondaryValue = rawSecondaryValue + '"';
                }
                tag[field.key] = context.cleanTagValue(rawPrimaryValue + rawSecondaryValue);
            }
        }

        dispatch.call('change', this, tag);
    }


    roadheight.tags = function(tags) {
        _tags = tags;

        var primaryValue = tags[field.key];
        var secondaryValue;
        var isMixed = Array.isArray(primaryValue);

        if (!isMixed) {
            if (primaryValue && (primaryValue.indexOf('\'') >= 0 || primaryValue.indexOf('"') >= 0)) {
                secondaryValue = primaryValue.match(/(-?[\d.]+)"/);
                if (secondaryValue !== null) {
                    secondaryValue = formatFloat(parseFloat(secondaryValue[1]));
                }
                primaryValue = primaryValue.match(/(-?[\d.]+)'/);
                if (primaryValue !== null) {
                    primaryValue = formatFloat(parseFloat(primaryValue[1]));
                }
                _isImperial = true;
            } else if (primaryValue) {
                var rawValue = primaryValue;
                primaryValue = parseFloat(rawValue);
                if (isNaN(primaryValue)) {
                    primaryValue = rawValue;
                } else {
                    primaryValue = formatFloat(primaryValue);
                }
                _isImperial = false;
            }
        }

        setUnitSuggestions();

        // If feet are specified but inches are omitted, assume zero inches.
        var inchesPlaceholder = formatFloat(0);

        utilGetSetValue(primaryInput, typeof primaryValue === 'string' ? primaryValue : '')
            .attr('title', isMixed ? primaryValue.filter(Boolean).join('\n') : null)
            .attr('placeholder', isMixed ? t('inspector.multiple_values') : t('inspector.unknown'))
            .classed('mixed', isMixed);
        utilGetSetValue(secondaryInput, typeof secondaryValue === 'string' ? secondaryValue : '')
            .attr('placeholder', isMixed ? t('inspector.multiple_values') : (_isImperial ? inchesPlaceholder : null))
            .classed('mixed', isMixed)
            .classed('disabled', !_isImperial)
            .attr('readonly', _isImperial ? null : 'readonly');
        secondaryUnitInput.attr('value', _isImperial ? t('inspector.roadheight.inch') : null);
    };


    roadheight.focus = function() {
        primaryInput.node().focus();
    };


    roadheight.entityIDs = function(val) {
        _entityIDs = val;
    };


    function combinedEntityExtent() {
        return _entityIDs && _entityIDs.length && utilTotalExtent(_entityIDs, context.graph());
    }


    return utilRebind(roadheight, dispatch, 'on');
}
