import { __decorate, __metadata } from "tslib";
import { h, Host } from "@stencil/core";
import { BEM } from "../../utils/bem";
import { defaultConfig, ListenToConfig } from "../../utils/config";
import { raf, rOnLoad } from "../../utils/helpers";
import { Logger } from "../../utils/log";
export class Spinner {
    constructor() {
        this.animated = defaultConfig.animated;
        /**
         * PUBLIC PROPERTY API
         * ------------------------------------------------------
         */
        /**
         * If `true` the component can be used on dark background
         */
        this.inverted = false;
        /**
         * If `true` the component will not add the spinner animation svg
         */
        this.deactivated = false;
        /**
         * Defines the color of the spinner.
         */
        this.color = 'blue';
        /**
         * If `true` the component is smaller
         */
        this.small = false;
        /**
         * Defines the look of the spinner
         */
        this.variation = 'logo';
        /**
         * PRIVATE METHODS
         * ------------------------------------------------------
         */
        this.animate = async () => {
            if (!this.animated) {
                this.destroy();
                return;
            }
            await this.load();
            if (this.currentRaf !== undefined) {
                cancelAnimationFrame(this.currentRaf);
            }
            if (this.shouldAnimate()) {
                this.destroy();
                this.currentRaf = raf(async () => {
                    if (this.animationFunction) {
                        this.animationFunction(this.el, this.getColor());
                    }
                });
            }
        };
        this.destroy = () => {
            if (this.animationItem && this.animationItem.destroy) {
                this.animationItem.destroy();
            }
            this.el.innerHTML = '';
        };
        this.shouldAnimate = () => {
            if (this.variation !== 'logo') {
                return false;
            }
            if (typeof window === 'undefined') {
                return false;
            }
            if (this.animationFunction === undefined) {
                return false;
            }
            return !this.deactivated;
        };
        this.load = async () => {
            return new Promise((resolve, reject) => {
                if (this.animationFunction) {
                    return resolve();
                }
                else {
                    rOnLoad(async () => {
                        import(/* @vite-ignore */ './bal-spinner.animation')
                            .then(module => {
                            this.animationFunction = module.animate;
                            resolve();
                        })
                            .catch(reject);
                    });
                }
            });
        };
    }
    createLogger(log) {
        this.log = log;
    }
    deactivatedWatcher(newValue, oldValue) {
        if (newValue !== oldValue) {
            if (this.deactivated) {
                this.destroy();
            }
            else {
                this.animate();
            }
        }
    }
    variationWatcher(newValue, oldValue) {
        if (newValue !== oldValue) {
            if (this.variation === 'circle') {
                this.destroy();
            }
            else {
                this.animate();
            }
        }
    }
    /**
     * LIFECYCLE
     * ------------------------------------------------------
     */
    componentDidLoad() {
        if (this.variation === 'logo') {
            this.animate();
        }
        else {
            this.destroy();
        }
    }
    disconnectedCallback() {
        if (this.el && !this.el.isConnected) {
            this.destroy();
        }
    }
    /**
     * LISTENERS
     * ------------------------------------------------------
     */
    configChanged(state) {
        this.animated = state.animated;
        if (state.animated === false) {
            this.destroy();
        }
    }
    /**
     * GETTERS
     * ------------------------------------------------------
     */
    getColor() {
        return this.inverted || this.color === 'white' ? '#ffffff' : '#151f6d';
    }
    /**
     * RENDER
     * ------------------------------------------------------
     */
    render() {
        const block = BEM.block('spinner');
        return (h(Host, { key: 'bf00a08aaa12fd4a3473d6f277a62abe4537ee8f', class: Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({}, block.class()), block.modifier('circle').class(this.variation === 'circle')), block.modifier('small').class(this.small)), block.modifier('animated').class(this.animated)), block.modifier(`color-${this.color}`).class(this.variation === 'circle')), role: "progressbar", "aria-hidden": "true" }));
    }
    static get is() { return "bal-spinner"; }
    static get originalStyleUrls() {
        return {
            "$": ["bal-spinner.sass"]
        };
    }
    static get styleUrls() {
        return {
            "$": ["bal-spinner.css"]
        };
    }
    static get properties() {
        return {
            "inverted": {
                "type": "boolean",
                "mutable": false,
                "complexType": {
                    "original": "boolean",
                    "resolved": "boolean",
                    "references": {}
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [],
                    "text": "If `true` the component can be used on dark background"
                },
                "getter": false,
                "setter": false,
                "reflect": false,
                "attribute": "inverted",
                "defaultValue": "false"
            },
            "deactivated": {
                "type": "boolean",
                "mutable": false,
                "complexType": {
                    "original": "boolean",
                    "resolved": "boolean",
                    "references": {}
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [],
                    "text": "If `true` the component will not add the spinner animation svg"
                },
                "getter": false,
                "setter": false,
                "reflect": false,
                "attribute": "deactivated",
                "defaultValue": "false"
            },
            "color": {
                "type": "string",
                "mutable": false,
                "complexType": {
                    "original": "BalProps.BalSpinnerColor",
                    "resolved": "\"blue\" | \"white\"",
                    "references": {
                        "BalProps": {
                            "location": "global",
                            "id": "global::BalProps"
                        }
                    }
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [],
                    "text": "Defines the color of the spinner."
                },
                "getter": false,
                "setter": false,
                "reflect": false,
                "attribute": "color",
                "defaultValue": "'blue'"
            },
            "small": {
                "type": "boolean",
                "mutable": false,
                "complexType": {
                    "original": "boolean",
                    "resolved": "boolean",
                    "references": {}
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [],
                    "text": "If `true` the component is smaller"
                },
                "getter": false,
                "setter": false,
                "reflect": false,
                "attribute": "small",
                "defaultValue": "false"
            },
            "variation": {
                "type": "string",
                "mutable": false,
                "complexType": {
                    "original": "BalProps.BalSpinnerVariation",
                    "resolved": "\"circle\" | \"logo\"",
                    "references": {
                        "BalProps": {
                            "location": "global",
                            "id": "global::BalProps"
                        }
                    }
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [],
                    "text": "Defines the look of the spinner"
                },
                "getter": false,
                "setter": false,
                "reflect": false,
                "attribute": "variation",
                "defaultValue": "'logo'"
            }
        };
    }
    static get states() {
        return {
            "animated": {}
        };
    }
    static get elementRef() { return "el"; }
    static get watchers() {
        return [{
                "propName": "deactivated",
                "methodName": "deactivatedWatcher"
            }, {
                "propName": "variation",
                "methodName": "variationWatcher"
            }];
    }
}
__decorate([
    Logger('bal-spinner'),
    __metadata("design:type", Function),
    __metadata("design:paramtypes", [Function]),
    __metadata("design:returntype", void 0)
], Spinner.prototype, "createLogger", null);
__decorate([
    ListenToConfig(),
    __metadata("design:type", Function),
    __metadata("design:paramtypes", [Object]),
    __metadata("design:returntype", void 0)
], Spinner.prototype, "configChanged", null);
