/**
 * @since Last modified: 2024-09-10 11:20:41
 * @class Swipe
 * @description Folding too long text and omittind.
 * @param {*} elem - target element
 * @param {Object} [options] - Parameters
 * @see {@link https://codepen.io/axui/pen/ZEwvpNL|demo @ codepen}
 * @example
 * ax.Swipe('#id');
 */
import getEl from '../utils/getEl';
import isEmpty from '../utils/isEmpty';
import instance from '../utils/instance';
import createEl from '../utils/createEl';
import PubBase from './PubBase';
import PubListen from './PubListen';
import PubUpdate from './PubUpdate';
import PubCommon from './PubCommon';
import pipe from '../utils/pipe';
import optSwipe from '../options/optSwipe';
import throttle from '../utils/throttle';
import prefix from '../global/prefix';
import Spy from './Spy';
import getDataType from '../utils/getDataType';
import isNull from '../utils/isNull';
import extend from '../utils/extend';
import Scroll from './Scroll';
import getSlidersData from '../utils/getSlidersData';
import toNumber from '../utils/toNumber';
import style from '../utils/style';
import Observe from './Observe';
import clampVal from '../utils/clampVal';
import unique from '../utils/unique';
import setSingleSel from '../utils/setSingleSel';
import getSelectorType from '../utils/getSelectorType';
import classes from '../utils/classes';
import Progress from './Progress';
import delay from '../utils/delay';
class Swipe extends pipe(PubListen, PubUpdate, PubCommon)(PubBase) {
    constructor(elem, options, initial = true) {
        super();
        this.options = {};
        this.ready({
            options,
            maps: optSwipe,
            host: elem,
            component: true,
            spread: ['autoplay', 'total', 'tools', 'pgn', 'nav', 'centered']
        });
        this.countdownEl = createEl('div');
        this.intervalEvt = () => {
            this.toNextBullet();
            this.startCountdown();
        };
        this.startClone = [];
        this.endClone = [];
        this.sliderTpl = { label: '', content: '', thumb: '', brief: '', slider: null, cb: null };
        this.prepareListen = throttle(() => {
            this.fillWedgets();
            this.setBulletActive(this.bullets.find((k) => this.actIdx === k.index) || 0);
            this.toggleNavDisabled();
            this.targetEl.classList.remove(`${prefix}launched`);
            this.setAutoPlay();
        });
        this.resetListener = throttle(() => {
            this.getSingleSize();
            this.setSlideSize();
            (this.group > this.sliders.length) && (this.group = this.sliders.length);
            super.listen({ name: 'resized' });
        });
        this.setBulletActive = (data) => {
            let bullet = this.findBullet(data);
            if (!bullet || bullet.active)
                return;
            bullet.active = true;
            let other = this.bullets.find((k) => k !== bullet && k.active);
            other && Reflect.deleteProperty(other, 'active');
            /* if (this.pgnIns && this.pgnIns.options.slides > 0) {
                let index = this.pgnIns.actIdx, bulletIndex = this.bullets.findIndex(k => k.active);
                if (this.pgnIns.actIdx + this.pgnIns.options.slides <= bulletIndex) {
                    index = bulletIndex - this.pgnIns.options.slides + 1;
                } else if (bulletIndex < this.pgnIns.actIdx) {
                    index = bulletIndex;
                }
                this.pgnIns.scrollIns.setSnapped({ target: this.pgnIns.slides[index].dom });
            } */
        };
        super.listen({ name: 'ready' });
        if (initial) {
            if (this.options.lazy) {
                this.spyIns = new Spy(this.targetEl, {
                    repeat: false,
                    onIn: () => {
                        this.init();
                    }
                });
            }
            else {
                this.init();
            }
        }
    }
    async init(cb) {
        super.listen({ name: 'launch' });
        this.options.b4Init && await this.options.b4Init.call(this);
        this.slidersTmp = [];
        this.bulletsTmp = [];
        this.paused = true;
        this.setAttrs();
        this.createWrap();
        await this.getSliders(this.options.content, (resp) => {
            this.slidersTmp = resp;
        });
        this.setSlidesObs();
        this.setBulletsObs();
        this.actIdx = this.getIdxFromActive(this.options.active);
        this.appendSliders();
        this.group = clampVal({ val: this.options.group, min: 0, max: this.sliders.length });
        this.setScroll();
        super.listen({ name: 'init', cb });
        return this;
    }
    /**
    * @callback fn_cb_init
    * @description Execute a function after destroy.
    * @returns null.
    */
    /**
    * @description Set attributes and styles to the target node after initialization.
    * @returns null
    */
    setAttrs() {
        this.targetEl.classList.add(`${prefix}swipe`);
    }
    getDriftParams() {
        if (this.group)
            return { enable: true, mode: 'snap', value: 1 };
        let tmp = { mode: 'auto', coef: 6 };
        if (typeof this.options.drift === 'number' && this.options.drift > 0) {
            tmp = { mode: 'snap', value: this.options.divide * this.options.drift };
        }
        else if (this.options.drift === 'viewport' && this.options.slides > 0) {
            tmp = { mode: 'snap', value: this.options.slides * this.options.divide };
        }
        return { enable: true, ...tmp };
    }
    getWheelVal() {
        return this.options.divide * (this.group ? 1 : this.options.wheel);
    }
    setScroll() {
        this.scrollOpt = extend({
            target: {
                wrapper: this.wrapEl,
                gridded: this.options.divide > 1 ? true : false,
                axis: this.options.axis,
                keyboard: this.options.keyboard,
                snap: {
                    enable: true,
                    selector: this.options.unalign,
                },
                wheel: {
                    mode: 'snap',
                    value: this.getWheelVal(),
                },
                drift: this.getDriftParams(),
                initial: {
                    value: this.getInitSlider(),
                },
                duration: this.options.duration,
                resizeThr: this.options.slides > 0 ? 2 : 1,
                paddingStart: this.options.centered.enable ? 'center' : 0,
                paddingEnd: this.options.centered.enable ? 'center' : 0,
                child: { size: (this.options.slides > 0 ? `1 / ${this.options.slides}` : null), gap: this.options.gap },
                onGetSnappeds: function () {
                },
                onPrepared: this.prepareListen,
                onRefactored: this.resetListener,
                onResized: this.resetListener,
                onSnap: (slider) => {
                    if (this.scrollIns.initialResize) {
                        this.actIdx = this.sliders.findIndex((k) => k.slider === slider);
                        this.setBulletActive(slider);
                    }
                    (this.options.autoHeight && this.options.axis === 'x') && (this.targetEl.style.height = style(slider).height);
                },
                onSnapped: (slider) => {
                },
                onMove: () => {
                    this.pause(true);
                }
            },
            source: this.options.scroll
        });
        if (this.group && this.options.slides > 1) {
        }
        if (this.options.slides >= 1) {
        }
        this.scrollIns = new Scroll(this.targetEl, this.scrollOpt);
    }
    async getSliders(data = this.options.content, cb) {
        let result = [];
        await getSlidersData.call(this, {
            content: data,
            contType: this.options.contType,
            contData: this.options.contData,
            ajax: this.options.ajax,
            hyphen: this.options.hyphen,
            parent: this.targetEl,
            wrap: this.wrapEl,
            lazy: this.options.lazy,
            tplStr: this.options.tplStr,
            tplEng: this.options.tplEng,
            cb: (resp) => {
                result = [...resp];
            }
        });
        cb && cb(result);
        return result;
    }
    findSlider(data) {
        let dataType = getDataType(data), result;
        if (dataType === 'Number') {
            result = this.sliders[data]?.slider;
        }
        else if (dataType === 'Object') {
            result = data?.slider;
        }
        else {
            result = getEl(data, this.wrapEl);
        }
        return result;
    }
    appendSliders(data = this.sliders, placement = 'end') {
        let target, sliders = data.map((k) => k.slider);
        if (placement === 'start') {
            sliders.reverse();
            for (let k of sliders) {
                this.wrapEl.insertAdjacentElement('afterbegin', k);
            }
        }
        else if (placement === 'end') {
            this.wrapEl.append(...sliders);
        }
        else {
            target = this.findSlider(placement);
            if (target) {
                sliders.reverse();
                for (let k of sliders) {
                    target.insertAdjacentElement('afterend', k);
                }
            }
        }
    }
    createWrap() {
        let firstChild = this.targetEl.firstElementChild;
        if (firstChild) {
            firstChild.classList.add(`${prefix}swipe-wrap`);
            this.wrapEl = firstChild;
        }
        else {
            this.wrapEl = createEl('ul', { class: `${prefix}swipe-wrap ${prefix}reset` }, '');
            this.targetEl.appendChild(this.wrapEl);
        }
        if (this.targetEl.querySelector(`.${prefix}swipe-nav`)) {
            this.navEl = this.targetEl.querySelector(`.${prefix}swipe-nav`);
        }
        else if (this.options.integrated) {
            this.navEl = createEl('div', { class: `${prefix}swipe-nav` }, '');
            this.targetEl.appendChild(this.navEl);
        }
    }
    fillWedgets() {
        this.getBullets();
        this.fillNav();
        this.fillPgn();
        this.fillTotal();
    }
    updateWedgets() {
        this.getBullets();
        this.updatePgn();
        this.updateTotal();
    }
    setSlidesObs() {
        this.slidersObs = new Observe(this.slidersTmp, {
            onComplete: () => {
                this.updateGap();
                this.updateWedgets();
                this.scrollIns.setSnapped({ force: true });
            }
        });
        this.sliders = this.slidersObs.proxy;
    }
    setBulletsObs() {
        this.bulletsObs = new Observe(this.bulletsTmp, {
            deep: true,
            onSet: (resp) => {
                if (resp.key === 'active' && resp.value === true) {
                    resp.proxy.el.setAttribute('active', '');
                    this.bulletSeq = this.findPrevNextBullet(resp.proxy);
                    this.toBullet(resp.proxy);
                    this.toggleNavDisabled(resp.proxy);
                    this.numEl && (this.numEl.innerHTML = this.bullets.findIndex((k) => k === resp.proxy) + 1);
                }
            },
            onDelete: (resp) => {
                if (resp.key === 'active') {
                    resp.target.el.removeAttribute('active');
                }
            },
            onComplete: () => {
            }
        });
        this.bullets = this.bulletsObs.proxy;
    }
    findPrevNextBullet(data) {
        let item = this.findBullet(data);
        if (!item)
            return { prev: null, next: null };
        let idx = this.bullets.findIndex((k) => k === item), prev = this.bullets[idx - 1], next = this.bullets[idx + 1];
        if (!prev) {
            if (this.options.loop) {
            }
            else if (this.options.autoplay.enable) {
                prev = this.bullets.at(-1);
            }
        }
        if (!next) {
            if (this.options.loop) {
            }
            else if (this.options.autoplay.enable) {
                next = this.bullets[0];
            }
        }
        return { prev, next, current: item };
    }
    toggleNavDisabled(data) {
        if (this.options.loop || !this.options.nav.enable)
            return;
        if (this.bullets.length < 2) {
            this.prevEl.setAttribute('disabled', '');
            this.nextEl.setAttribute('disabled', '');
        }
        else {
            let item = this.findBullet(data);
            if (!item)
                return;
            if (item === this.bullets[0]) {
                this.prevEl.setAttribute('disabled', '');
                this.nextEl.removeAttribute('disabled');
            }
            else if (item === this.bullets.at(-1)) {
                this.nextEl.setAttribute('disabled', '');
                this.prevEl.removeAttribute('disabled');
            }
            else {
                this.prevEl.removeAttribute('disabled');
                this.nextEl.removeAttribute('disabled');
            }
        }
    }
    setSlideSize() {
        if (this.options.slides > 0) {
            this.sliders.forEach((k) => {
                this.setSingleSize(k);
            });
            this.updateGap();
        }
    }
    updateGap() {
        if (this.options.slides > 0) {
            if (this.options.divide > 1) {
                this.sliders.forEach((k, i) => {
                    this.setSingleGap(k, i);
                });
            }
            else {
                if (this.options.gap > 0) {
                    this.sliders.forEach((k) => {
                        this.setSingleGap(k);
                    });
                }
            }
        }
    }
    /*     getActiveSlider(active?: number | T_sel) {
            let result = null;
            if (typeof active == 'number') {
                result = this.sliders[active];
            } else {
                result = getEl(active, this.targetEl);
            }
            return result;
        }
        toggleActive(slider: T_obj) {
            if (!slider) return;
            slider.active = true;
            for (let k of this.sliders) {
                if (k === slider) continue;
                Reflect.deleteProperty(k, 'active');
            }
        } */
    getIdxFromActive(active) {
        let result = this.getActiveIdex(active);
        return clampVal({ val: result, min: 0, max: this.sliders.length - 1 });
    }
    getActiveIdex(data) {
        let result = -1;
        if (typeof data === 'number') {
            result = data;
        }
        else {
            let tmp = getEl(data, this.targetEl);
            tmp && (result = this.sliders.findeIndex((k) => k.slider === tmp));
        }
        result >= this.sliders.length && (result = -1);
        return result;
    }
    getInitSlider() {
        if (this.sliders.length === 0 || this.actIdx === -1)
            return null;
        if (this.options.centered.enable && this.options.centered.fill) {
            if (this.options.slides > 1 && this.actIdx < ~~(this.options.slides / 2)) {
                this.actIdx = ~~(this.options.slides / 2);
            }
        }
        return this.sliders[this.actIdx].slider;
    }
    getAccuracy(value, higher = true) {
        let places = value.toString().split(".")[1] ? value.toString().split(".")[1].length : 0;
        return places > 3 ? toNumber(value + (higher ? 0.1 : 0), { mode: higher ? 'ceil' : 'floor', places: 1 }) : value;
    }
    getSingleSize() {
        if (!(this.options.slides > 0))
            return;
        this.slideSize = this.getAccuracy(this.scrollIns.childAvgSize, this.scrollIns.gap > 0 ? false : true);
        if (this.options.divide > 1) {
            let netValueDivide = this.scrollIns.reverseSize - this.scrollIns.gap * (this.options.divide - 1), singleValueDivide = netValueDivide / this.options.divide;
            this.slideSizeDivide = this.getAccuracy(singleValueDivide, this.scrollIns.gap > 0 ? false : true);
        }
    }
    setSingleSize(item) {
        if (!(this.options.slides > 0))
            return;
        item.slider.style[this.scrollIns.propsMap.size] = this.slideSize + 'px';
    }
    setSingleGap(item, index) {
        if (!(this.options.slides > 0))
            return;
        let idx = isNull(index) ? this.sliders.findIndex((k) => k === item) : index;
        if (this.options.divide > 1) {
            item.slider.style[this.scrollIns.propsMap.reverse.size] = this.getAccuracy(this.slideSizeDivide, false) + 'px';
            if (idx % this.options.divide !== 0 && this.scrollIns.gap) {
                item.slider.style[this.scrollIns.propsMap.reverse.gap] = this.scrollIns.gap + 'px';
            }
            idx >= this.options.divide && (item.slider.style[this.scrollIns.propsMap.gap] = this.scrollIns.gap + 'px');
        }
        else {
            idx !== 0 && (item.slider.style[this.scrollIns.propsMap.gap] = this.scrollIns.gap + 'px');
        }
    }
    getBullets() {
        this.bullets.length = 0;
        let unsnappeds = [], len = this.sliders.length;
        if (this.options.slides > 0) {
            this.sliders.forEach((k, i) => {
                let obj = { target: k, el: createEl('li'), index: i };
                if (this.options.centered.enable) {
                    this.bullets.push(obj);
                }
                else {
                    if (this.options.loop) {
                        if (this.group && this.options.slides > 1) {
                            if (i % (this.options.slides * this.options.divide) === 0) {
                                this.bullets.push(obj);
                            }
                            else {
                                k.slider.setAttribute(this.options.unalign, '');
                            }
                        }
                        else {
                            this.bullets.push(obj);
                        }
                    }
                    else {
                        let num = this.options.divide * (this.group || this.options.slides);
                        if ((i % num === 0 && this.sliders.length - i >= num) || i === len - num) {
                            this.bullets.push(obj);
                        }
                        else {
                            if (this.group) {
                                unsnappeds.push(k.slider);
                                setSingleSel(k.slider, this.options.unalign);
                            }
                        }
                    }
                    this.updateUnsnappeds(unsnappeds);
                }
            });
        }
        else {
            if (this.scrollIns.isBaby) {
                this.bullets.push({ target: this.sliders[0], el: createEl('li'), index: 0 });
            }
            else {
                let splits = this.getSplits(), tmp = this.getSanpOffsetArr();
                for (let k of tmp) {
                    for (let v of splits) {
                        ((k.offsetStart <= v && k.offsetEnd > v)) && this.bullets.push({ target: k.target, el: createEl('li'), index: k.index });
                    }
                }
            }
        }
    }
    updateUnsnappeds(unsnappeds) {
        this.scrollIns.unsnappeds = unique([...this.scrollIns.unsnappeds, ...unsnappeds]);
        this.scrollIns.snappeds = [...this.wrapEl.children].filter(k => !this.scrollIns.unsnappeds.includes(k));
    }
    getSplits() {
        let num = Math.floor(this.scrollIns.wrapSize / this.scrollIns.baseSize), getSplits = (num, unit) => {
            let result = [];
            for (let k = 0; k < num; k++) {
                result.push(k * unit);
            }
            return result;
        }, result = getSplits(num, this.scrollIns.baseSize);
        result.push(this.scrollIns.wrapSize - this.scrollIns.baseSize);
        return result;
    }
    getSanpOffsetArr() {
        let result = [];
        this.sliders.forEach((k, i) => {
            if (this.scrollIns.snappeds.includes(k.slider)) {
                let idx = this.scrollIns.snappeds.findIndex((v) => v === k.slider), nextSnapped = this.scrollIns.snappeds[idx + 1], offsetStart = k.slider[this.scrollIns.propsMap.offset], offsetEnd = nextSnapped ? this.scrollIns.snappeds[idx + 1][this.scrollIns.propsMap.offset] : offsetStart + k.slider[this.scrollIns.propsMap.dim];
                result.push({ offsetStart, offsetEnd, target: k, index: i });
            }
        });
        return result;
    }
    updateTotal(value = this.getTotal()) {
        if (!this.options.total.enable)
            return false;
        if (!value.bullets) {
            this.numEl.innerHTML = this.denomEl.innerHTML = 0;
        }
        else {
            this.numEl.innerHTML = value.curBullet + 1;
            this.denomEl.innerHTML = value.bullets;
        }
    }
    fillTotal() {
        if (!this.options.total.enable)
            return false;
        let total = this.getTotal();
        this.totalEl = createEl('span', { class: `${prefix}swipe-total` }, `<i></i><s>${this.options.total.hyphen}</s><u></u>`);
        this.numEl = this.totalEl.querySelector('i');
        this.denomEl = this.totalEl.querySelector('u');
        this.updateTotal(total);
        this.options.total.placement && this.totalEl.setAttribute('placement', this.options.total.placement);
        this.targetEl.appendChild(this.totalEl);
    }
    getTotal() {
        return { curSlider: this.actIdx, sliders: this.sliders.length, curBullet: this.bullets.findIndex((k) => k.active), bullets: this.bullets.length };
    }
    fillNav() {
        if (!this.options.nav.enable)
            return false;
        let addNav = (type) => {
            let result = null, text = (type === 'prev') ? (this.options.axis === 'x' ? 'left' : 'up') :
                (type === 'next') ? (this.options.axis === 'x' ? 'right' : 'down') : '', className = `${prefix}swipe-${type}`, el = this.targetEl.querySelector(`.${className}`);
            if (el) {
                result = el;
            }
            else if (this.options.nav[type].selector) {
                result = getEl(this.options.nav[type].selector);
            }
            else {
                result = createEl('i', { class: className }, text);
                this.navEl ? this.navEl.appendChild(result) : this.targetEl.appendChild(result);
            }
            if (result) {
                this.options.nav[type].classes && classes.add(result, this.options.nav[type].classes);
                this.options.nav[type].text && (result.innerHTML = this.options.nav[type].text);
                this.options.nav.classes && classes.add(result, this.options.nav.classes);
                this.options.nav.fill && result.setAttribute('filled', '');
            }
            return result;
        };
        if (this.options.nav.enable) {
            this.prevEl = addNav('prev');
            this.nextEl = addNav('next');
            if (this.prevEl) {
                this.prevEl.onclick = throttle(() => {
                    this.toPrevBullet();
                }, { intvl: this.options.nav.intvl, prevent: true });
            }
            if (this.nextEl) {
                this.nextEl.onclick = throttle(() => {
                    this.toNextBullet();
                }, { intvl: this.options.nav.intvl, prevent: true });
            }
        }
    }
    fillPgn() {
        if (!this.options.pgn.enable)
            return false;
        this.pgnIns = null;
        let className = `${prefix}swipe-pgn`, pgnTmp = [...this.targetEl.children].find((k) => k.classList.contains(className));
        if (pgnTmp) {
            this.pgnEl = pgnTmp;
        }
        else if (this.options.pgn.selector) {
            let selType = getDataType(this.options.pgn.selector);
            if (selType.includes('HTML')) {
                this.pgnEl = this.options.pgn.selector;
            }
            else if (selType === 'String') {
                if (getSelectorType(this.options.pgn.selector)) {
                    this.pgnEl = getEl(this.options.pgn.selector);
                }
                else {
                    this.pgnIns = instance.find(this.options.pgn.selector, 'swipe');
                    this.pgnIns && (this.pgnEl = this.pgnIns.wrapEl);
                }
            }
            else if (selType === 'Object') {
                this.pgnIns = this.options.pgn.selector;
                this.pgnEl = this.pgnIns.wrapEl;
            }
        }
        else {
            this.pgnEl = createEl('ul', { class: `${className} ${prefix}reset` }, '');
            this.navEl && this.prevEl ? this.prevEl.insertAdjacentElement('afterend', this.pgnEl) : this.targetEl.appendChild(this.pgnEl);
        }
        if (this.pgnEl) {
            this.options.pgn.type && this.pgnEl.setAttribute('type', this.options.pgn.type);
            this.options.pgn.classes && classes.add(this.pgnEl, this.options.pgn.classes);
            if (this.pgnEl.children.length) {
                this.bullets.forEach((k, i) => {
                    if (this.pgnEl.children[i]) {
                        k.el = this.pgnEl.children[i];
                        i === this.actIdx && this.setBulletActive(k);
                    }
                });
                this.setBulletAction();
            }
            else {
                this.updatePgn();
            }
        }
    }
    setBulletAction() {
        this.bullets.forEach((k) => {
            k.el.onclick = () => {
                this.setBulletActive(k);
                this.scrollIns.scrollTo({ target: k.target.slider, snap: true });
            };
        });
    }
    updatePgn() {
        if (!this.options.pgn.enable)
            return;
        this.pgnEl.innerHTML = '';
        let len = this.bullets.length, fragment = document.createDocumentFragment();
        this.bullets.forEach((k, i) => {
            i === this.actIdx && this.setBulletActive(k);
            let html;
            switch (this.options.pgn.type) {
                case 'text':
                    html = k.target.source.label || this.options.pgn.data[i];
                    break;
                case 'thumb':
                    html = `<img src="${k.target.source.thumb || this.options.pgn.data[i]}"/>`;
                    break;
                case 'index':
                    html = i + 1;
                    break;
                default:
                    html = '';
            }
            if (this.options.pgn.before) {
                this.options.pgn.before.call(this, { index: i, total: len, html, bullet: k, parent: this.pgnEl });
            }
            else {
                k.el.innerHTML = html;
            }
            fragment.appendChild(k.el);
        });
        this.pgnEl.appendChild(fragment);
        this.options.pgn.after && this.options.pgn.after.call(this, { total: len, parent: this.pgnEl });
        this.setBulletAction();
    }
    findNavSnap(type = 'next') {
        let index = this.scrollIns.snappeds.findIndex((k) => k === this.scrollIns.snapped), target = null;
        if (index < 0)
            return target;
        if (type === 'next') {
            if (this.options.loop && index === this.scrollIns.snappeds.length - 1) {
                target = this.scrollIns.snappeds[0];
            }
            else {
                index !== this.scrollIns.snappeds.length - 1 && (target = this.scrollIns.snappeds[index + 1]);
            }
        }
        else if (type === 'prev') {
            if (this.options.loop && index === 0) {
                target = this.scrollIns.snappeds.at(-1);
            }
            else {
                index !== 0 && (target = this.scrollIns.snappeds[index - 1]);
            }
        }
        else if (type === 'start') {
            target = this.scrollIns.snappeds[0];
        }
        else if (type === 'end') {
            target = this.scrollIns.snappeds.at(-1);
        }
        return target;
    }
    findSnap(data) {
        let dataType = getDataType(data), result;
        if (dataType === 'Number') {
            let tmp = this.sliders[data];
            result = tmp && this.scrollIns.snappeds.includes(tmp.slider) ? tmp : null;
        }
        else if (dataType.includes('HTML') || dataType === 'String') {
            let tmp = getEl(data, this.wrapEl);
            result = tmp && this.scrollIns.snappeds.includes(tmp) ? tmp : null;
        }
        else if (dataType === 'Object' && data.hasOwnProperty('slider')) {
            result = this.scrollIns.snappeds.includes(data.slider) ? data : null;
        }
        return result;
    }
    findBullet(data) {
        let dataType = getDataType(data), result;
        if (dataType === 'Number') {
            result = this.bullets[data];
        }
        else if (dataType.includes('HTML') || dataType === 'String') {
            result = this.bullets.find((k) => k.target.slider === getEl(data, this.wrapEl));
        }
        else if (dataType === 'Object' && data.hasOwnProperty('el')) {
            result = data;
        }
        return result;
    }
    toBullet(data, opt = {}) {
        if (this.destroyed)
            return;
        let bullet = this.findBullet(data);
        if (!bullet || this.bulletSeq.current === bullet)
            return;
        this.scrollIns.scrollTo({
            target: bullet.target.slider,
            snap: true,
            before: () => {
                this.setBulletActive(bullet);
                opt.before && opt.before.call(this, bullet);
            },
            after: () => {
                opt.after && opt.after.call(this, bullet);
            }
        });
    }
    toPrevBullet(cb) {
        if (this.destroyed)
            return;
        this.bulletSeq.prev && this.toBullet(this.bulletSeq.prev, {
            after: () => {
                cb && cb.call(this, this.bulletSeq.prev);
            }
        });
    }
    toNextBullet(cb) {
        if (this.destroyed)
            return;
        this.bulletSeq.next && this.toBullet(this.bulletSeq.next, {
            after: () => {
                cb && cb.call(this, this.bulletSeq.next);
            }
        });
    }
    toSnap(data, opt = {}) {
        if (this.destroyed)
            return;
        let target = this.findSnap(data);
        if (!target || this.scrollIns.snapped === target)
            return;
        this.scrollIns.scrollTo({
            target,
            snap: true,
            before: () => {
                opt.before && opt.before.call(this, target);
            },
            after: () => {
                opt.after && opt.after.call(this, target);
            }
        });
    }
    toPrevSnap(cb) {
        if (this.destroyed)
            return;
        let target = this.findNavSnap('prev');
        if (!target)
            return;
        this.scrollIns.scrollTo({
            target,
            snap: true,
            after: () => {
                cb && cb.call(this, target);
            }
        });
    }
    toNextSnap(cb) {
        if (this.destroyed)
            return;
        if (this.destroyed)
            return;
        let target = this.findNavSnap('next');
        if (!target)
            return;
        this.scrollIns.scrollTo({
            target,
            snap: true,
            after: () => {
                cb && cb.call(this, target);
            }
        });
    }
    toStart(cb) {
        if (this.destroyed)
            return;
        let item = this.bullets[0];
        if (item.active)
            return;
        this.toBullet(item, {
            after: (bullet) => {
                cb && cb.call(this, bullet);
            }
        });
    }
    toEnd(cb) {
        if (this.destroyed)
            return;
        let item = this.bullets.at(-1);
        if (item.active)
            return;
        this.toBullet(item, {
            after: (bullet) => {
                cb && cb.call(this, bullet);
            }
        });
    }
    setLoopPlay() {
        if (this.options.loop === false) {
            return false;
        }
        if (this.options.slides === 'auto') {
            this.startClone = this.slides.map((k) => k.dom.cloneNode(true));
            this.endClone = this.slides.map((k) => k.dom.cloneNode(true));
            this.totalClone = this.slides.length;
        }
        else {
            this.startClone = this.slides.slice(0, this.options.slides).map((k) => k.dom.cloneNode(true));
            this.endClone = this.slides.slice(this.slides.length - this.options.slides).map((k) => k.dom.cloneNode(true));
            this.totalClone = this.options.slides;
        }
        this.scrollIns.add(this.endClone, { placement: 'start' });
        this.scrollIns.add(this.startClone, { placement: 'end' });
    }
    startCountdown() {
        if (!this.countdownIns)
            return;
        this.countdownIns.setCompleted();
        this.countdownIns.animateTo(0, { duration: this.options.autoplay.delay });
    }
    setAutoPlay() {
        if (!this.options.autoplay.enable)
            return;
        if (this.options.autoplay.countdown) {
            if (!this.countdownIns) {
                this.countdownIns = new Progress(this.countdownEl, extend({
                    target: {
                        label: false,
                        type: 'circle',
                        curve: 'linear',
                        size: 'xxs',
                        control: true,
                        duration: this.options.autoplay.delay,
                        onPause: () => {
                            this.pause();
                        },
                        onContinue: (resp) => {
                            this.continue(resp.durRest);
                        }
                    },
                    source: this.options.countdown,
                }));
            }
            else {
                this.countdownIns.init();
            }
            this.targetEl.appendChild(this.countdownEl);
        }
        this.play();
    }
    continue(duration) {
        delay({
            duration,
            done: () => {
                this.toNextBullet(() => {
                    this.play();
                });
            }
        });
    }
    play(delay, cb) {
        if (this.destroyed || !this.paused)
            return;
        if (!this.options.autoplay.enable)
            return;
        this.interval && clearInterval(this.interval);
        this.interval = setInterval(this.intervalEvt, delay || this.options.autoplay.delay);
        this.startCountdown();
        this.paused = false;
        super.listen({ name: 'play', cb });
        return this;
    }
    pause(clear = false, cb) {
        if (this.destroyed || this.paused)
            return;
        if (!this.options.autoplay.enable)
            return;
        clearInterval(this.interval);
        if (clear && this.countdownIns) {
            this.countdownEl.remove();
            this.countdownIns.destroy();
        }
        this.paused = true;
        super.listen({ name: 'pause', cb });
        return this;
    }
    async add(data, options) {
        if (this.destroyed || isEmpty(data))
            return;
        let tmp, opts = Object.assign({ placement: 'end' }, options);
        await this.getSliders(data, (resp) => {
            tmp = resp;
            this.sliders.push(...tmp);
        });
        this.appendSliders(tmp, opts.placement);
        super.listen({ name: 'add', cb: opts.cb, params: [tmp] });
        return { ins: this, data: tmp };
    }
    remove(data = 'end', cb) {
        if (this.destroyed || isEmpty(data))
            return;
        let tmp;
        if (data === 'start') {
            tmp = this.sliders[0]?.slider;
        }
        else if (data === 'end') {
            tmp = this.sliders.at(-1)?.slider;
        }
        else {
            tmp = this.findSlider(data);
        }
        if (!tmp)
            return;
        tmp.remove();
        super.listen({ name: 'remove', cb, params: [this.sliders.find((k) => k.slider === tmp)] });
        return this;
    }
    destroy(cb) {
        if (this.destroyed)
            return this;
        for (let k of this.sliders) {
            k.spy && k.spy.destroy();
        }
        this.scrollIns.destroy();
        this.spyIns && this.spyIns.destroy();
        this.countdownIns && this.countdownIns.destroy();
        window.removeEventListener('keydown', this.keyToSwipe);
        this.bullets.forEach((k) => {
            k.el.onclick = null;
        });
        this.prevEl && (this.prevEl.onclick = null);
        this.nextEl && (this.nextEl.onclick = null);
        if (this.toolsEl) {
            this.options.tools.children.forEach((k) => {
                k.el.onclick = null;
            });
        }
        this.destroyed = true;
        super.listen({ name: 'destroy', cb });
        return this;
    }
    updateCont(text, cb) {
        if (this.destroyed) {
            return this;
        }
        this.options.content = text;
        this.init();
        super.updateCache({ content: this.content });
        super.listen({ name: 'updateCont', cb, params: [this.content] });
        return this;
    }
}
Swipe.hostType = 'node';
export default Swipe;
