import { h } from '../edel-elements.core.js';

var ToastKind;
(function (ToastKind) {
    ToastKind["default"] = "info";
    ToastKind["info"] = "info";
    ToastKind["good"] = "good";
    ToastKind["bad"] = "bad";
    ToastKind["warning"] = "warning";
})(ToastKind || (ToastKind = {}));
const allToastKinds = [
    ToastKind.info,
    ToastKind.good,
    ToastKind.bad,
    ToastKind.warning
];
function isToastKind(value) {
    return allToastKinds.indexOf(value) !== -1;
}

class EdelToastComponent {
    constructor() {
        this.kind = ToastKind.default;
        this.noClose = false;
    }
    render() {
        return [
            h("div", { class: "toast-icon" }, this.renderToastIcon()),
            h("div", { class: "toast-label" },
                h("slot", null)),
            this.noClose ? null : this.renderCloseButton()
        ];
    }
    hostData() {
        return {
            class: 'toast'
        };
    }
    componentDidLoad() {
        this.handleKindChange(this.kind, ToastKind.default);
    }
    handleKindChange(newValue, oldValue) {
        if (isToastKind(newValue) === false) {
            this.kind = ToastKind.default;
        }
        if (isToastKind(oldValue)) {
            this.host.classList.remove(`toast--${oldValue}`);
        }
        this.host.classList.add(`toast--${this.kind}`);
    }
    renderToastIcon() {
        const iconNamed = (name, size) => (h("i", { class: `fa fa-${name} fa-w-${size}` }));
        switch (this.kind) {
            case ToastKind.info:
                return iconNamed('exclamation-triangle', 18);
            case ToastKind.good:
                return iconNamed('check-circle', 16);
            case ToastKind.bad:
                return iconNamed('times', 12);
            case ToastKind.warning:
                return iconNamed('exclamation-triangle', 18);
            default:
                return null;
        }
    }
    renderCloseButton() {
        return (h("div", { class: "toast-action" },
            h("edel-button", { icon: "times", slim: true, plain: true, onEmit: () => this.close.emit() })));
    }
    static get is() { return "edel-toast"; }
    static get properties() { return {
        "host": {
            "elementRef": true
        },
        "kind": {
            "type": String,
            "attr": "kind",
            "mutable": true,
            "watchCallbacks": ["handleKindChange"]
        },
        "noClose": {
            "type": Boolean,
            "attr": "no-close"
        }
    }; }
    static get events() { return [{
            "name": "close",
            "method": "close",
            "bubbles": true,
            "cancelable": true,
            "composed": true
        }]; }
}

class EdelToastgroupComponent {
    constructor() {
        this.toasts = [];
        this.duration = 10000;
        this.canClose = true;
        this.now = () => Date.now();
    }
    hostData() {
        return {
            class: 'toastgroup'
        };
    }
    render() {
        return [
            this.toasts.map(toast => (h("edel-toast", { kind: toast.kind, "no-close": !toast.options.canClose, onClose: toast.close }, toast.message))),
            h("slot", null)
        ];
    }
    cleanExpiredToasts() {
        const current = this.currentTimestamp();
        this.removeToastsWhere(toast => toast.options.expire !== 0 && toast.options.expire <= current, true);
    }
    good(message, options = {}) {
        return this.presentToast(ToastKind.good, message, options);
    }
    bad(message, options = {}) {
        return this.presentToast(ToastKind.bad, message, options);
    }
    info(message, options = {}) {
        return this.presentToast(ToastKind.info, message, options);
    }
    warning(message, options = {}) {
        return this.presentToast(ToastKind.warning, message, options);
    }
    componentDidLoad() {
        this.didLoad.emit(this);
    }
    presentToast(kind, message, options) {
        const closable = {
            message,
            kind,
            options: this.canonicalToastOptions(options),
            close: () => this.removeToast(closable)
        };
        this.toasts = [closable, ...this.toasts];
        this.scheduleCleanFor(closable);
        return closable;
    }
    currentTimestamp() {
        return this.now instanceof Function ? this.now() : this.now;
    }
    expiration(options) {
        const duration = typeof options.duration === 'number' ? options.duration : this.duration;
        if (duration === 0)
            return 0;
        const expire = typeof options.expire === 'number'
            ? options.expire
            : this.currentTimestamp() + duration;
        return expire;
    }
    scheduleCleanFor(closable) {
        if (this.now instanceof Function) {
            setTimeout(() => this.cleanExpiredToasts(), closable.options.expire - this.currentTimestamp());
        }
    }
    removeToast(closable) {
        this.removeToastsWhere(toast => toast === closable, false);
    }
    removeToastsWhere(predicate, expired) {
        this.toasts = this.toasts.filter(toast => {
            if (predicate(toast)) {
                toast.options.didClose(expired);
                return false;
            }
            else {
                return true;
            }
        });
    }
    canonicalToastOptions(options) {
        return {
            canClose: typeof options.canClose === 'boolean'
                ? options.canClose
                : this.canClose,
            expire: this.expiration(options),
            didClose: options.didClose || (() => void 0)
        };
    }
    static get is() { return "edel-toastgroup"; }
    static get properties() { return {
        "bad": {
            "method": true
        },
        "canClose": {
            "type": Boolean,
            "attr": "can-close"
        },
        "duration": {
            "type": Number,
            "attr": "duration"
        },
        "good": {
            "method": true
        },
        "info": {
            "method": true
        },
        "now": {
            "type": Number,
            "attr": "now",
            "watchCallbacks": ["cleanExpiredToasts"]
        },
        "toasts": {
            "state": true
        },
        "warning": {
            "method": true
        }
    }; }
    static get events() { return [{
            "name": "didLoad",
            "method": "didLoad",
            "bubbles": true,
            "cancelable": true,
            "composed": true
        }]; }
}

export { EdelToastComponent as EdelToast, EdelToastgroupComponent as EdelToastgroup };
