import { defineVxeComponent } from '../../ui/src/comp';
import XEUtils from 'xe-utils';
import { getConfig, getIcon, createEvent, globalMixins, renderEmptyElement } from '../../ui';
import { getSlotVNs } from '../../ui/src/vn';
import { toCssUnit } from '../../ui/src/dom';
import VxeLoadingComponent from '../../loading/src/loading';
export default {
    name: 'VxeCarousel',
    mixins: [
        globalMixins.sizeMixin
    ],
    props: {
        value: [String, Number],
        options: Array,
        loading: Boolean,
        height: {
            type: [Number, String],
            default: () => getConfig().carousel.height
        },
        width: {
            type: [Number, String],
            default: () => getConfig().carousel.width
        },
        autoPlay: {
            type: Boolean,
            default: () => getConfig().carousel.autoPlay
        },
        interval: {
            type: [Number, String],
            default: () => getConfig().carousel.interval
        },
        loop: {
            type: Boolean,
            default: () => getConfig().carousel.loop
        },
        vertical: {
            type: Boolean,
            default: () => getConfig().carousel.vertical
        },
        showIndicators: {
            type: Boolean,
            default: () => getConfig().carousel.showIndicators
        }
    },
    data() {
        const xID = XEUtils.uniqueId();
        const reactData = {
            activeName: '',
            staticItems: [],
            itemWidth: 0,
            itemHeight: 0
        };
        const internalData = {
            apTimeout: undefined,
            stopFlag: false
        };
        return {
            xID,
            reactData,
            internalData
        };
    },
    provide() {
        const $xeCarousel = this;
        return {
            $xeCarousel
        };
    },
    computed: Object.assign(Object.assign({}, {}), { computeListStyle() {
            const $xeCarousel = this;
            const props = $xeCarousel;
            const reactData = $xeCarousel.reactData;
            const { vertical, options } = props;
            const { activeName, itemWidth, itemHeight, staticItems } = reactData;
            const list = (staticItems && staticItems.length ? staticItems : options) || [];
            const activeIndex = Math.max(0, XEUtils.findIndexOf(list, item => item.name === activeName));
            const stys = {};
            if (vertical) {
                stys.transform = `translateY(-${activeIndex * itemHeight}px)`;
            }
            else {
                stys.width = `${itemWidth * list.length}px`;
                stys.transform = `translateX(-${activeIndex * itemWidth}px)`;
            }
            return stys;
        } }),
    methods: {
        //
        // Method
        //
        dispatchEvent(type, params, evnt) {
            const $xeCarousel = this;
            $xeCarousel.$emit(type, createEvent(evnt, { $carousel: $xeCarousel }, params));
        },
        emitModel(value) {
            const $xeCarousel = this;
            const { _events } = $xeCarousel;
            $xeCarousel.$emit('input', value);
            if (_events && _events.modelValue) {
                $xeCarousel.$emit('modelValue', value);
            }
            else {
                $xeCarousel.$emit('model-value', value);
            }
        },
        prev() {
            const $xeCarousel = this;
            if ($xeCarousel.handlePrevNext(false)) {
                $xeCarousel.handleAutoPlay();
            }
            return $xeCarousel.$nextTick();
        },
        next() {
            const $xeCarousel = this;
            if ($xeCarousel.handlePrevNext(true)) {
                $xeCarousel.handleAutoPlay();
            }
            return $xeCarousel.$nextTick();
        },
        updateStyle() {
            const $xeCarousel = this;
            const reactData = $xeCarousel.reactData;
            $xeCarousel.$nextTick(() => {
                const wrapperElem = $xeCarousel.$refs.refWrapperElem;
                if (wrapperElem) {
                    reactData.itemWidth = wrapperElem.clientWidth;
                    reactData.itemHeight = wrapperElem.clientHeight;
                }
            });
        },
        clickItemEvent(evnt, item) {
            const $xeCarousel = this;
            const reactData = $xeCarousel.reactData;
            const value = item.name;
            reactData.activeName = item.name;
            $xeCarousel.emitModel(value);
            $xeCarousel.$emit('change', { value }, evnt);
            $xeCarousel.updateStyle();
        },
        initDefaultActive(list) {
            const $xeCarousel = this;
            const props = $xeCarousel;
            const reactData = $xeCarousel.reactData;
            let activeName = null;
            if (list && list.length) {
                let validVal = false;
                activeName = props.value;
                list.forEach((item) => {
                    if (activeName === item.name) {
                        validVal = true;
                    }
                });
                if (!validVal) {
                    activeName = list[0].name;
                    $xeCarousel.emitModel(activeName);
                }
            }
            reactData.activeName = activeName;
        },
        handlePrevNext(isNext) {
            const $xeCarousel = this;
            const props = $xeCarousel;
            const reactData = $xeCarousel.reactData;
            const { options, loop } = props;
            const { activeName, staticItems } = reactData;
            const list = (staticItems && staticItems.length ? staticItems : options) || [];
            const index = Math.max(0, XEUtils.findIndexOf(list, item => item.name === activeName));
            if (index > -1) {
                let item = null;
                if (isNext) {
                    if (index < list.length - 1) {
                        item = list[index + 1];
                    }
                    else {
                        if (loop) {
                            item = list[0];
                        }
                    }
                }
                else {
                    if (index > 0) {
                        item = list[index - 1];
                    }
                    else {
                        if (loop) {
                            item = list[list.length - 1];
                        }
                    }
                }
                if (item) {
                    const name = item.name;
                    const value = name;
                    reactData.activeName = name;
                    $xeCarousel.emitModel(value);
                    return true;
                }
            }
            return false;
        },
        prevEvent(evnt) {
            const $xeCarousel = this;
            const reactData = $xeCarousel.reactData;
            if ($xeCarousel.handlePrevNext(false)) {
                const value = reactData.activeName;
                $xeCarousel.$emit('change', { value }, evnt);
            }
        },
        nextEvent(evnt) {
            const $xeCarousel = this;
            const reactData = $xeCarousel.reactData;
            if ($xeCarousel.handlePrevNext(true)) {
                const value = reactData.activeName;
                $xeCarousel.$emit('change', { value }, evnt);
            }
        },
        stopAutoPlay() {
            const $xeCarousel = this;
            const internalData = $xeCarousel.internalData;
            const { apTimeout } = internalData;
            internalData.stopFlag = true;
            if (apTimeout) {
                clearTimeout(apTimeout);
                internalData.apTimeout = undefined;
            }
        },
        handleAutoPlay() {
            const $xeCarousel = this;
            const props = $xeCarousel;
            const internalData = $xeCarousel.internalData;
            const { autoPlay, interval } = props;
            const { stopFlag } = internalData;
            $xeCarousel.stopAutoPlay();
            if (autoPlay) {
                internalData.stopFlag = false;
                internalData.apTimeout = setTimeout(() => {
                    if (!stopFlag) {
                        $xeCarousel.handlePrevNext(true);
                    }
                }, XEUtils.toNumber(interval) || 300);
            }
        },
        mouseenterEvent() {
            const $xeCarousel = this;
            $xeCarousel.stopAutoPlay();
        },
        mouseleaveEvent() {
            const $xeCarousel = this;
            $xeCarousel.handleAutoPlay();
        },
        callSlot(slotFunc, params) {
            const $xeCarousel = this;
            const slots = $xeCarousel.$scopedSlots;
            if (slotFunc) {
                if (XEUtils.isString(slotFunc)) {
                    slotFunc = slots[slotFunc] || null;
                }
                if (XEUtils.isFunction(slotFunc)) {
                    return getSlotVNs(slotFunc(params));
                }
            }
            return [];
        },
        //
        // Render
        //
        renderItemWrapper(h, list) {
            const $xeCarousel = this;
            const props = $xeCarousel;
            const reactData = $xeCarousel.reactData;
            const { height } = props;
            const { activeName } = reactData;
            const listStyle = $xeCarousel.computeListStyle;
            return h('div', {
                class: 'vxe-carousel--list',
                style: listStyle
            }, list.map(item => {
                const { name, url, slots } = item;
                const defaultSlot = slots ? slots.default : null;
                return h('div', {
                    key: `${name}`,
                    class: ['vxe-carousel--item-inner', {
                            'is--active': activeName === name
                        }],
                    style: height
                        ? {
                            height: toCssUnit(height)
                        }
                        : {}
                }, defaultSlot
                    ? $xeCarousel.callSlot(defaultSlot, {})
                    : [
                        h('img', {
                            class: 'vxe-carousel--item-img',
                            attrs: {
                                src: url
                            }
                        })
                    ]);
            }));
        },
        renderIndicators(h, list) {
            const $xeCarousel = this;
            const reactData = $xeCarousel.reactData;
            const { activeName } = reactData;
            return h('div', {
                class: 'vxe-carousel--indicators'
            }, list.map((item) => {
                const { name } = item;
                return h('div', {
                    key: `${name}`,
                    class: ['vxe-carousel--indicators-item', {
                            'is--active': activeName === name
                        }],
                    on: {
                        click(evnt) {
                            $xeCarousel.clickItemEvent(evnt, item);
                        }
                    }
                });
            }));
        },
        renderVN(h) {
            const $xeCarousel = this;
            const props = $xeCarousel;
            const slots = $xeCarousel.$scopedSlots;
            const reactData = $xeCarousel.reactData;
            const { loading, height, width, showIndicators, vertical, options } = props;
            const { staticItems } = reactData;
            const defaultSlot = slots.default;
            const list = (staticItems && staticItems.length ? staticItems : options) || [];
            return h('div', {
                ref: 'refElem',
                class: ['vxe-carousel', `is--${vertical ? 'vertical' : 'horizontal'}`],
                style: width
                    ? {
                        width: toCssUnit(width)
                    }
                    : {},
                on: {
                    mouseenter: $xeCarousel.mouseenterEvent,
                    mouseleave: $xeCarousel.mouseleaveEvent
                }
            }, [
                h('div', {
                    class: 'vxe-carousel--slots'
                }, defaultSlot ? defaultSlot({}) : []),
                h('div', {
                    ref: 'refWrapperElem',
                    class: 'vxe-carousel--item-wrapper',
                    style: height
                        ? {
                            height: toCssUnit(height)
                        }
                        : {}
                }, [
                    $xeCarousel.renderItemWrapper(h, list)
                ]),
                showIndicators ? $xeCarousel.renderIndicators(h, list) : renderEmptyElement($xeCarousel),
                h('div', {
                    class: 'vxe-carousel--btn-wrapper'
                }, [
                    h('div', {
                        class: 'vxe-carousel--previous-btn',
                        on: {
                            click: $xeCarousel.prevEvent
                        }
                    }, [
                        h('i', {
                            class: vertical ? getIcon().CAROUSEL_VERTICAL_PREVIOUS : getIcon().CAROUSEL_HORIZONTAL_PREVIOUS
                        })
                    ]),
                    h('div', {
                        class: 'vxe-carousel--next-btn',
                        on: {
                            click: $xeCarousel.nextEvent
                        }
                    }, [
                        h('i', {
                            class: vertical ? getIcon().CAROUSEL_VERTICAL_NEXT : getIcon().CAROUSEL_HORIZONTAL_NEXT
                        })
                    ])
                ]),
                /**
                 * 加载中
                 */
                h(VxeLoadingComponent, {
                    class: 'vxe-carousel--loading',
                    props: {
                        value: loading
                    }
                })
            ]);
        }
    },
    watch: {
        options() {
            const $xeCarousel = this;
            const props = $xeCarousel;
            $xeCarousel.initDefaultActive(props.options);
        },
        'reactData.staticItems'() {
            const $xeCarousel = this;
            const reactData = $xeCarousel.reactData;
            $xeCarousel.initDefaultActive(reactData.staticItems);
        },
        autoPlay() {
            const $xeCarousel = this;
            $xeCarousel.handleAutoPlay();
        }
    },
    created() {
        const $xeCarousel = this;
        const props = $xeCarousel;
        const reactData = $xeCarousel.reactData;
        $xeCarousel.initDefaultActive(reactData.staticItems.length ? reactData.staticItems : props.options);
    },
    mounted() {
        const $xeCarousel = this;
        $xeCarousel.handleAutoPlay();
        $xeCarousel.updateStyle();
    },
    beforeDestroy() {
        const $xeCarousel = this;
        $xeCarousel.stopAutoPlay();
    },
    render(h) {
        return this.renderVN(h);
    }
};
