(function (global, factory) {
    typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('@angular/core'), require('@angular/common'), require('ngx-bootstrap/carousel'), require('@wm/components/base'), require('@swipey'), require('lodash-es')) :
    typeof define === 'function' && define.amd ? define(['exports', '@angular/core', '@angular/common', 'ngx-bootstrap/carousel', '@wm/components/base', '@swipey', 'lodash-es'], factory) :
    (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory((global.wm = global.wm || {}, global.wm.components = global.wm.components || {}, global.wm.components.advanced = global.wm.components.advanced || {}, global.wm.components.advanced.carousel = {}), global.ng.core, global.ng.common, global.carousel, global.wm.components.base, global.swipey, global._));
})(this, (function (exports, i0, common, i1, base, _swipey, lodashEs) { 'use strict';

    function _interopNamespaceDefault(e) {
        var n = Object.create(null);
        if (e) {
            Object.keys(e).forEach(function (k) {
                if (k !== 'default') {
                    var d = Object.getOwnPropertyDescriptor(e, k);
                    Object.defineProperty(n, k, d.get ? d : {
                        enumerable: true,
                        get: function () { return e[k]; }
                    });
                }
            });
        }
        n.default = e;
        return Object.freeze(n);
    }

    var i0__namespace = /*#__PURE__*/_interopNamespaceDefault(i0);
    var i1__namespace = /*#__PURE__*/_interopNamespaceDefault(i1);

    const registerProps$1 = () => {
        base.register('wm-carousel', new Map([
            ['animation', { value: 'auto', ...base.PROP_STRING }],
            ['animationinterval', { value: 3, ...base.PROP_NUMBER }],
            ['controls', { value: 'both', ...base.PROP_STRING }],
            ['dataset', base.PROP_ANY],
            ['name', base.PROP_STRING],
            ['nodatamessage', { value: 'No Data Found', ...base.PROP_STRING }],
            ['show', base.PROP_BOOLEAN]
        ]));
    };

    class CarouselAnimator extends _swipey.SwipeAnimation {
        constructor(carousel, interval, ngZone) {
            super();
            this.carousel = carousel;
            this.interval = interval;
            this.ngZone = ngZone;
            this._activeIndex = 0;
            this._animationPaused = false;
            this._pauseCaroselTill = 0;
            this._oldIndex = 0;
            const self = this;
            this._$el = $(this.carousel.getNativeElement()).find('>.carousel');
            this.init(this._$el.find('>.carousel-inner'));
            this._items = this._$el.find('>.carousel-inner >.carousel-item');
            this._indicators = this._$el.find('>.carousel-indicators');
            this._indicators.find('li').each(function (i) {
                $(this).on('click', () => {
                    self._activeIndex = i;
                    self.setActiveItem();
                    // WMS-17583: Triggering onChange event
                    self.carousel.onChangeCB(self._activeIndex, self._oldIndex);
                    self._oldIndex = self._activeIndex;
                });
            });
            this._$el.find('>.left.carousel-control').on('click', () => {
                // WMS-22278, If a swipe is already in process do not process other events
                if (this._swiping) {
                    return;
                }
                this._pauseCaroselTill = Date.now() + this.interval;
                this.goToUpper();
            });
            this._$el.find('>.right.carousel-control').on('click', () => {
                // WMS-22278, If a swipe is already in process do not process other events
                if (this._swiping) {
                    return;
                }
                this._pauseCaroselTill = Date.now() + this.interval;
                this.goToLower();
            });
            this.setActiveItem();
            if (this.interval) {
                this.start();
            }
            $('carousel slide').removeAttr('aria-hidden');
        }
        bounds() {
            this._width = this._items.width();
            this._swiping = true;
            return {
                'lower': -this._width,
                'center': 0,
                'upper': this._width
            };
        }
        context() {
            return {
                'w': this._width
            };
        }
        animation() {
            return [{
                    'target': this.getTarget.bind(this),
                    'css': {
                        'transform': 'translate3d(${{ (($D + $d) / w) * 100 + \'%\'}}, 0, 0)',
                        '-webkit-transform': 'translate3d(${{ (($D + $d) / w) * 100 + \'%\'}}, 0, 0)'
                    }
                }];
        }
        onUpper() {
            this.resetTransition();
            this._activeIndex -= 1;
            this.setActiveItem();
            this._swiping = false;
        }
        onLower() {
            this.resetTransition();
            this._activeIndex += 1;
            this.setActiveItem();
            this._swiping = false;
        }
        onAnimation() {
            const newIndex = (this._items.length + this._activeIndex) % this._items.length;
            this.carousel.onChangeCB(newIndex, this._oldIndex);
            this._oldIndex = newIndex;
            const activeElementIndex = lodashEs.findIndex(this._items, this._$el.find('>.carousel-inner >.carousel-item.active')[0]);
            this._$el.find('>.left.carousel-control').attr('aria-label', (activeElementIndex === 0 ? this._items.length : activeElementIndex) + ' of ' + this._items.length);
            this._$el.find('>.right.carousel-control').attr('aria-label', (activeElementIndex === this._items.length - 1 ? 1 : activeElementIndex + 2) + ' of ' + this._items.length);
        }
        start() {
            this.ngZone.runOutsideAngular(() => {
                this._intervalId = setInterval(() => {
                    if (!this._swiping && this._pauseCaroselTill < Date.now()) {
                        this.goToLower(600);
                    }
                }, this.interval);
            });
        }
        pause() {
            this._animationPaused = true;
            if (!this._intervalId) {
                this.start();
            }
        }
        resume() {
            this._animationPaused = false;
        }
        stop() {
            if (this._intervalId) {
                clearInterval(this._intervalId);
                this._intervalId = 0;
            }
        }
        threshold() {
            return 5;
        }
        // Returns multiple elements as single jQuery element.
        getTarget() {
            const noOfItems = this._items.length, activeItem = this._items.eq((noOfItems + this._activeIndex) % noOfItems), leftItem = this._items.eq((noOfItems + this._activeIndex - 1) % noOfItems), rightItem = this._items.eq((noOfItems + this._activeIndex + 1) % noOfItems);
            return activeItem.add(rightItem).add(leftItem);
        }
        resetTransition() {
            this.getTarget().css({
                '-webkit-transition': 'none',
                '-webkit-transform': '',
                'transition': 'none',
                'transform': ''
            });
        }
        // Sets active item, leftItem, rightItem by removing / adding respective classes.
        setActiveItem() {
            const items = this._items, left = this._activeIndex - 1, right = this._activeIndex + 1;
            // if there is only one carousel-item then there won't be any right or left-item.
            if (items.length === 1) {
                items.eq(0).removeClass('left-item right-item');
                return;
            }
            this._indicators.find('>.active').removeClass('active');
            this._indicators.find('> li').eq((items.length + this._activeIndex) % items.length).addClass('active');
            items.filter('.active').removeClass('active');
            items.addClass('left-item');
            items.eq((items.length + left) % items.length).addClass('left-item').removeClass('right-item');
            items.eq((items.length + this._activeIndex) % items.length).removeClass('left-item right-item').addClass('active');
            items.eq((items.length + right) % items.length).addClass('right-item').removeClass('left-item');
        }
    }

    const WIDGET_CONFIG$1 = {
        widgetType: 'wm-carousel'
    };
    const navigationClassMap = {
        indicators: 'hide-navs',
        navs: 'hide-indicators',
        none: 'hide-both'
    };
    class CarouselDirective extends base.StylableComponent {
        static { this.initializeProps = registerProps$1(); }
        constructor(component, inj, ngZone, explicitContext) {
            super(inj, WIDGET_CONFIG$1, explicitContext);
            this.component = component;
            this.ngZone = ngZone;
            base.styler(this.nativeElement, this);
        }
        onDataChange(newVal) {
            this.fieldDefs = base.createArrayFrom(newVal);
        }
        stopAnimation() {
            if (this.animator) {
                this.animator.stop();
            }
        }
        startAnimation() {
            if (this.animator) {
                this.animator.interval = this.animationinterval * 1000;
                this.animator.start();
            }
        }
        onSlidesRender(slides) {
            // if dynamic carousel, initialize the 'currentslide' property as the first object
            if (this.fieldDefs && this.fieldDefs.length) {
                this.currentslide = this.fieldDefs[0];
            }
            if (slides.length) {
                setTimeout(() => {
                    this.animator = new CarouselAnimator(this, this.interval, this.ngZone);
                }, 50);
            }
        }
        setupHandlers() {
            this.slides.changes.subscribe(slides => {
                this.triggerAnimation(slides);
            });
            this.slides.setDirty();
        }
        onChangeCB(newIndex, oldIndex) {
            // assign current and previous slides on widget. In case of static carousel, fieldDefs will be undefined, hence the check
            this.currentslide = this.fieldDefs && this.fieldDefs[newIndex];
            this.previousslide = this.fieldDefs && this.fieldDefs[oldIndex];
            this.invokeEventCallback('change', { newIndex: newIndex, oldIndex: oldIndex });
        }
        ngAfterContentInit() {
            this.triggerAnimation(this.slides);
            this.setupHandlers();
        }
        ngOnDestroy() {
            this.stopAnimation();
            super.ngOnDestroy();
        }
        // Calculating animation interval if animation is enabled
        setanimationinterval() {
            this.interval = this.animation === 'auto' ? this.animationinterval * 1000 : 0;
        }
        triggerAnimation(slides) {
            this.stopAnimation();
            this.onSlidesRender(slides);
        }
        ngOnInit() {
            super.ngOnInit();
            this.setanimationinterval();
            // TODO transition is pending
        }
        // on property change handler
        onPropertyChange(key, nv, ov) {
            if (key === 'dataset') {
                this.onDataChange(nv);
            }
            else if (key === 'controls') {
                // For showing controls
                this.navigationClass = navigationClassMap[this.controls];
            }
            else if (key === 'animation' || key === 'animationinterval') {
                if (key === 'animationinterval') {
                    this.stopAnimation();
                    this.setanimationinterval();
                }
                this.animation === 'none' ? this.stopAnimation() : this.startAnimation();
            }
            else {
                super.onPropertyChange(key, nv, ov);
            }
        }
        static { this.ɵfac = function CarouselDirective_Factory(t) { return new (t || CarouselDirective)(i0__namespace.ɵɵdirectiveInject(i1__namespace.CarouselComponent), i0__namespace.ɵɵdirectiveInject(i0__namespace.Injector), i0__namespace.ɵɵdirectiveInject(i0__namespace.NgZone), i0__namespace.ɵɵdirectiveInject('EXPLICIT_CONTEXT', 8)); }; }
        static { this.ɵdir = /*@__PURE__*/ i0__namespace.ɵɵdefineDirective({ type: CarouselDirective, selectors: [["", "wmCarousel", ""]], contentQueries: function CarouselDirective_ContentQueries(rf, ctx, dirIndex) { if (rf & 1) {
                i0__namespace.ɵɵcontentQuery(dirIndex, i1.SlideComponent, 4);
            } if (rf & 2) {
                let _t;
                i0__namespace.ɵɵqueryRefresh(_t = i0__namespace.ɵɵloadQuery()) && (ctx.slides = _t);
            } }, exportAs: ["wmCarousel"], features: [i0__namespace.ɵɵInheritDefinitionFeature] }); }
    }
    (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0__namespace.ɵsetClassMetadata(CarouselDirective, [{
            type: i0.Directive,
            args: [{
                    selector: '[wmCarousel]',
                    exportAs: 'wmCarousel'
                }]
        }], () => [{ type: i1__namespace.CarouselComponent }, { type: i0__namespace.Injector }, { type: i0__namespace.NgZone }, { type: undefined, decorators: [{
                    type: i0.Inject,
                    args: ['EXPLICIT_CONTEXT']
                }, {
                    type: i0.Optional
                }] }], { slides: [{
                type: i0.ContentChildren,
                args: [i1.SlideComponent]
            }] }); })();

    const registerProps = () => {
        base.register('wm-carousel-template', new Map([
            ['show', base.PROP_BOOLEAN]
        ]));
    };

    const DEFAULT_CLS = 'app-carousel-item';
    const WIDGET_CONFIG = {
        widgetType: 'wm-carousel-template',
        hostClass: DEFAULT_CLS
    };
    class CarouselTemplateDirective extends base.StylableComponent {
        static { this.initializeProps = registerProps(); }
        constructor(inj, explicitContext) {
            super(inj, WIDGET_CONFIG, explicitContext);
            base.styler(this.nativeElement, this);
        }
        static { this.ɵfac = function CarouselTemplateDirective_Factory(t) { return new (t || CarouselTemplateDirective)(i0__namespace.ɵɵdirectiveInject(i0__namespace.Injector), i0__namespace.ɵɵdirectiveInject('EXPLICIT_CONTEXT', 8)); }; }
        static { this.ɵdir = /*@__PURE__*/ i0__namespace.ɵɵdefineDirective({ type: CarouselTemplateDirective, selectors: [["", "wmCarouselTemplate", ""]], exportAs: ["carouselTemplateRef"], features: [i0__namespace.ɵɵInheritDefinitionFeature] }); }
    }
    (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0__namespace.ɵsetClassMetadata(CarouselTemplateDirective, [{
            type: i0.Directive,
            args: [{
                    selector: '[wmCarouselTemplate]',
                    exportAs: 'carouselTemplateRef',
                }]
        }], () => [{ type: i0__namespace.Injector }, { type: undefined, decorators: [{
                    type: i0.Inject,
                    args: ['EXPLICIT_CONTEXT']
                }, {
                    type: i0.Optional
                }] }], null); })();

    const components = [
        CarouselDirective,
        CarouselTemplateDirective
    ];
    class CarouselModule {
        static { this.ɵfac = function CarouselModule_Factory(t) { return new (t || CarouselModule)(); }; }
        static { this.ɵmod = /*@__PURE__*/ i0__namespace.ɵɵdefineNgModule({ type: CarouselModule }); }
        static { this.ɵinj = /*@__PURE__*/ i0__namespace.ɵɵdefineInjector({ imports: [common.CommonModule,
                i1.CarouselModule,
                base.WmComponentsModule] }); }
    }
    (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0__namespace.ɵsetClassMetadata(CarouselModule, [{
            type: i0.NgModule,
            args: [{
                    imports: [
                        common.CommonModule,
                        i1.CarouselModule,
                        base.WmComponentsModule
                    ],
                    declarations: [...components],
                    exports: [...components]
                }]
        }], null, null); })();
    (function () { (typeof ngJitMode === "undefined" || ngJitMode) && i0__namespace.ɵɵsetNgModuleScope(CarouselModule, { declarations: [CarouselDirective,
            CarouselTemplateDirective], imports: [common.CommonModule,
            i1.CarouselModule,
            base.WmComponentsModule], exports: [CarouselDirective,
            CarouselTemplateDirective] }); })();

    exports.CarouselAnimator = CarouselAnimator;
    exports.CarouselDirective = CarouselDirective;
    exports.CarouselModule = CarouselModule;
    exports.CarouselTemplateDirective = CarouselTemplateDirective;

}));
