"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var tslib_1 = require("tslib");
var vdom_1 = require("@dojo/framework/core/vdom");
var theme_1 = require("../middleware/theme");
var string_1 = require("@dojo/framework/shim/string");
var list_1 = require("../list");
var focus_1 = require("@dojo/framework/core/middleware/focus");
var css = require("../theme/default/time-picker.m.css");
var inputCss = require("../theme/default/text-input.m.css");
var trigger_popup_1 = require("../trigger-popup");
var text_input_1 = require("../text-input");
var icon_1 = require("../icon");
var icache_1 = require("@dojo/framework/core/middleware/icache");
var util_1 = require("../common/util");
var TimePicker_1 = require("./nls/TimePicker");
var i18n_1 = require("@dojo/framework/core/middleware/i18n");
var resources_1 = require("@dojo/framework/core/middleware/resources");
var resource = resources_1.createResourceMiddleware();
var factory = vdom_1.create({
    resource: resource,
    theme: theme_1.default,
    i18n: i18n_1.default,
    focus: focus_1.default,
    icache: icache_1.createICacheMiddleware()
})
    .properties()
    .children();
var formats = {
    hh: {
        regex: /^(\d{1,2})$/i,
        positions: {
            hour: 1
        }
    },
    hhmm: {
        regex: /^(\d{1,2}):(\d{1,2})$/,
        positions: {
            hour: 1,
            minute: 2
        }
    },
    hhmmss: {
        regex: /^(\d{1,2}):(\d{1,2}):(\d{1,2})$/,
        positions: {
            hour: 1,
            minute: 2,
            second: 3
        }
    },
    hham: {
        regex: /^(\d{1,2})\s*([ap]\.?m\.?)$/i,
        positions: {
            hour: 1,
            amPm: 2
        }
    },
    hhmmam: {
        regex: /^(\d{1,2}):(\d{1,2})\s*([ap]\.?m\.?)$/i,
        positions: {
            hour: 1,
            minute: 2,
            amPm: 3
        }
    },
    hhmmssam: {
        regex: /^(\d{1,2}):(\d{1,2}):(\d{1,2})\s*([ap]\.?m\.?)$/i,
        positions: {
            hour: 1,
            minute: 2,
            second: 3,
            amPm: 4
        }
    }
};
var formats24 = ['hh', 'hhmm', 'hhmmss'];
var formats12 = ['hh', 'hhmm', 'hhmmss', 'hham', 'hhmmam', 'hhmmssam'];
var template = resources_1.createMemoryResourceTemplate();
function parseTime(time, hour12) {
    var e_1, _a;
    if (!time) {
        return undefined;
    }
    var timeFormats = hour12 ? formats12 : formats24;
    try {
        for (var timeFormats_1 = tslib_1.__values(timeFormats), timeFormats_1_1 = timeFormats_1.next(); !timeFormats_1_1.done; timeFormats_1_1 = timeFormats_1.next()) {
            var key = timeFormats_1_1.value;
            var format = formats[key];
            var match = format.regex.exec(time);
            if (match) {
                var hours = format.positions.hour ? parseInt(match[format.positions.hour], 0) : 0;
                var minutes = format.positions.minute
                    ? parseInt(match[format.positions.minute], 0)
                    : 0;
                var seconds = format.positions.second
                    ? parseInt(match[format.positions.second], 0)
                    : 0;
                if (hour12 &&
                    format.positions.amPm &&
                    match[format.positions.amPm].toLocaleLowerCase()[0] === 'p' &&
                    hours !== 12) {
                    // special case for "12pm", which is just 12
                    hours += 12;
                }
                else if (hour12 &&
                    format.positions.amPm &&
                    match[format.positions.amPm].toLocaleLowerCase()[0] === 'a' &&
                    hours === 12) {
                    // special case of "12am", which we want to be hour 0
                    hours = 0;
                }
                if (hours === undefined || isNaN(hours) || isNaN(minutes) || isNaN(seconds)) {
                    return undefined;
                }
                return new Date(1970, 0, 1, hours, minutes, seconds, 0);
            }
        }
    }
    catch (e_1_1) { e_1 = { error: e_1_1 }; }
    finally {
        try {
            if (timeFormats_1_1 && !timeFormats_1_1.done && (_a = timeFormats_1.return)) _a.call(timeFormats_1);
        }
        finally { if (e_1) throw e_1.error; }
    }
    return undefined;
}
exports.parseTime = parseTime;
function format24HourTime(dt) {
    return string_1.padStart(String(dt.getHours()), 2, '0') + ":" + string_1.padStart(String(dt.getMinutes()), 2, '0') + ":" + string_1.padStart(String(dt.getSeconds()), 2, '0');
}
exports.format24HourTime = format24HourTime;
function isTimePickerChildren(children) {
    // In order to not make this a breaking change, check for an edge case where an object
    // with a label property that would have been used as a label might instead be treated as a render result
    return children && children.hasOwnProperty && children.hasOwnProperty('label');
}
exports.TimePicker = factory(function TimePicker(_a) {
    var id = _a.id, _b = _a.middleware, theme = _b.theme, icache = _b.icache, focus = _b.focus, i18n = _b.i18n, resource = _b.resource, properties = _a.properties, children = _a.children;
    var themedCss = theme.classes(css);
    var messages = i18n.localize(TimePicker_1.default).messages;
    var formatTime = function (time) {
        var _a = properties(), _b = _a.format, format = _b === void 0 ? '24' : _b, _c = _a.step, step = _c === void 0 ? 1800 : _c;
        var hideSeconds = step >= 60 && time.getSeconds() === 0;
        if (format === '24') {
            return time
                .toLocaleTimeString(undefined, {
                hour12: false,
                hour: 'numeric',
                minute: 'numeric',
                second: hideSeconds ? undefined : 'numeric'
            })
                .replace(/[^a-zA-Z\d\s:.]/g, '');
        }
        else {
            return time
                .toLocaleTimeString(undefined, {
                hour12: true,
                hour: 'numeric',
                minute: 'numeric',
                second: hideSeconds ? undefined : 'numeric'
            })
                .replace(/[^a-zA-Z\d\s:.]/g, '');
        }
    };
    var _c = properties(), initialValue = _c.initialValue, _d = _c.format, format = _d === void 0 ? '24' : _d, controlledValue = _c.value;
    if (initialValue !== undefined &&
        controlledValue === undefined &&
        icache.get('initialValue') !== initialValue) {
        var parsed = initialValue && parseTime(initialValue, format === '12');
        icache.set('inputValue', parsed ? formatTime(parsed) : '');
        icache.set('initialValue', initialValue);
        icache.set('shouldValidate', true);
    }
    if (controlledValue !== undefined && icache.get('lastValue') !== controlledValue) {
        var parsed = controlledValue && parseTime(controlledValue, format === '12');
        icache.set('inputValue', parsed ? formatTime(parsed) : '');
        icache.set('value', parsed ? format24HourTime(parsed) : '');
        icache.set('lastValue', controlledValue);
    }
    var inputValue = icache.getOrSet('inputValue', function () {
        var _a = properties(), initialValue = _a.initialValue, format = _a.format;
        var parsed = initialValue && parseTime(initialValue, format === '12');
        return parsed ? formatTime(parsed) : '';
    });
    var shouldValidate = icache.getOrSet('shouldValidate', true);
    var shouldFocus = focus.shouldFocus();
    var focusNode = icache.getOrSet('focusNode', 'input');
    if (shouldValidate) {
        var testValue = icache.get('nextValue') || inputValue;
        var _e = properties(), onValidate = _e.onValidate, onValue = _e.onValue, format_1 = _e.format;
        var max = parseTime(properties().max, format_1 === '12');
        var min = parseTime(properties().min, format_1 === '12');
        var isValid = icache.get('inputValid');
        var validationMessages = [];
        if (icache.get('inputValidMessage')) {
            validationMessages.push(icache.get('inputValidMessage') || '');
        }
        if (min && max && min > max) {
            validationMessages.push(messages.invalidProps);
            isValid = false;
        }
        else {
            var newTime = parseTime(testValue, format_1 === '12');
            if (newTime !== undefined) {
                if (min && newTime < min) {
                    validationMessages.push(messages.tooEarly);
                }
                else if (max && newTime > max) {
                    validationMessages.push(messages.tooLate);
                }
                else {
                    var twentyFourHourTime = format24HourTime(newTime);
                    if (controlledValue === undefined) {
                        icache.set('value', twentyFourHourTime);
                        icache.set('inputValue', formatTime(newTime));
                    }
                    if (onValue) {
                        onValue(twentyFourHourTime);
                    }
                }
            }
            else {
                if (inputValue) {
                    validationMessages.push(messages.invalidTime);
                }
            }
            isValid = validationMessages.length === 0;
            icache.set('isValid', isValid);
        }
        var validationMessage = validationMessages.join('; ');
        onValidate && onValidate(isValid, validationMessage);
        icache.set('validationMessage', validationMessage);
        icache.set('shouldValidate', false);
    }
    var generateOptions = function () {
        var _a = properties(), _b = _a.min, min = _b === void 0 ? '00:00:00' : _b, _c = _a.max, max = _c === void 0 ? '23:59:59' : _c, _d = _a.step, step = _d === void 0 ? 1800 : _d, timeDisabled = _a.timeDisabled;
        var options = [];
        var dt = parseTime(min, false) || new Date(1970, 0, 1, 0, 0, 0, 0);
        var end = parseTime(max, false) || new Date(1970, 0, 1, 23, 59, 59, 99);
        while (dt.getDate() === 1 && dt <= end) {
            var value = formatTime(dt);
            options.push({
                label: value,
                value: value,
                disabled: timeDisabled ? timeDisabled(dt) : false
            });
            dt.setSeconds(dt.getSeconds() + step);
        }
        return options;
    };
    var _f = properties(), name = _f.name, themeProp = _f.theme, classes = _f.classes, variant = _f.variant;
    var _g = tslib_1.__read(children(), 1), labelChild = _g[0];
    var label = isTimePickerChildren(labelChild) ? labelChild.label : labelChild;
    var options = generateOptions();
    return (vdom_1.tsx("div", { classes: [theme.variant(), themedCss.root] },
        vdom_1.tsx("input", { type: "hidden", name: name, value: icache.getOrSet('value', ''), "aria-hidden": "true" }),
        vdom_1.tsx(trigger_popup_1.default, { key: "popup", theme: themeProp, classes: classes, variant: variant }, {
            trigger: function (toggleOpen) {
                function openMenu() {
                    icache.set('focusNode', 'menu');
                    focus.focus();
                    toggleOpen();
                }
                var _a = properties(), disabled = _a.disabled, required = _a.required;
                return (vdom_1.tsx("div", { classes: themedCss.input },
                    vdom_1.tsx(text_input_1.default, { key: "input", disabled: disabled, required: required, focus: function () { return shouldFocus && focusNode === 'input'; }, theme: theme.compose(inputCss, css, 'input'), classes: classes, variant: variant, initialValue: icache.get('inputValue'), onBlur: function () { return icache.set('shouldValidate', true); }, onValue: function (v) {
                            return controlledValue === undefined
                                ? icache.set('inputValue', v || '')
                                : icache.set('nextValue', v || '');
                        }, helperText: icache.get('validationMessage'), valid: icache.get('isValid') && icache.get('inputValid'), onValidate: function (valid, message) {
                            if (valid !== icache.get('inputValid')) {
                                icache.set('inputValid', valid);
                                icache.set('inputValidMessage', message);
                            }
                        }, onKeyDown: function (key) {
                            if (key === util_1.Keys.Down || key === util_1.Keys.Enter) {
                                openMenu();
                            }
                        }, type: "text" }, {
                        label: label,
                        trailing: (vdom_1.tsx(text_input_1.Addon, { theme: themeProp, classes: classes, variant: variant },
                            vdom_1.tsx("button", { disabled: disabled, key: "clockIcon", onclick: function (e) {
                                    e.stopPropagation();
                                    openMenu();
                                }, classes: themedCss.toggleMenuButton, type: "button" },
                                vdom_1.tsx(icon_1.default, { type: "clockIcon" }))))
                    })));
            },
            content: function (onClose) {
                function closeMenu() {
                    icache.set('focusNode', 'input');
                    focus.focus();
                    onClose();
                }
                return (vdom_1.tsx("div", { key: "menu-wrapper", classes: themedCss.menuWrapper },
                    vdom_1.tsx(list_1.List, { theme: themeProp, classes: classes, variant: variant, key: "menu", focus: function () { return shouldFocus && focusNode === 'menu'; }, resource: resource({
                            template: template,
                            initOptions: { id: id, data: options }
                        }), onValue: function (value) {
                            if (controlledValue === undefined) {
                                icache.set('inputValue', value.value);
                            }
                            else {
                                icache.set('nextValue', value.value);
                            }
                            icache.set('shouldValidate', true);
                            closeMenu();
                        }, onRequestClose: closeMenu, onBlur: closeMenu, initialValue: '', menu: true })));
            }
        })));
});
exports.default = exports.TimePicker;

/*# sourceMappingURL=index.js.map*/