<!-- @author youboli -->
<!-- @email youboli@yangqianguan.com -->
<!-- @date 2023-01-12 13:34:38.000 -->
<!-- @desc generated by yqg-cli@5.9.3 -->

<script>

    import {
        useStorage,
        useWindowSize,
        useEventListener,
        promiseTimeout,
        get,
        set
    } from '@vueuse/core';
    import moment from 'moment';
    import _ from 'underscore';

    const DefaultPerday = 3;
    const StorageKey = 'FIREWORK';
    const store = useStorage(StorageKey, {perDay: 0, dateRange: [], expired: true});

    export default {
        name: 'YqgFirework',

        props: {
            getConfig: {
                type: Function,
                required: true
            },

            serializer: {
                type: [Array, String, Boolean],
                default: () => ['data', 'body', 'data']
            },

            options: {
                type: Object,
                default: () => ({})
            },

            zIndex: {
                type: Number,
                default: 1000
            },

            intervalPerLaunch: {
                type: Number,
                default: 1000
            },

            countPerLaunch: {
                type: Number,
                default: 12
            },

            launchCount: {
                type: Number,
                default: 2
            },

            disabledInFrame: {
                type: Boolean,
                default: true
            }
        },

        data() {
            const {zIndex} = this;

            return {
                firework: null,
                canFire: false,
                style: {
                    width: 0,
                    height: 0,
                    position: 'fixed',
                    top: 0,
                    left: 0,
                    zIndex
                }
            };
        },

        async mounted() {
            if (this.disabledInFrame && self !== top) return;

            const {Fireworks} = await import('fireworks-js');

            await this.setStore();

            const canFire = this.checkCanFire();

            if (!canFire) return;

            this.$nextTick(() => {
                const firework = new Fireworks(this.$refs.container, this.options);

                this.firework = firework;

                this.updateCanvasSize();

                this.launch(() => {
                    this.style.zIndex = -1;
                    this.style.display = 'none';
                    store.value.perDay = (get(store)?.perDay ?? 0) - 1;
                });
            });

            const cleanWindowResize = useEventListener(window, 'resize', this.updateCanvasSize);

            this.$once('hook:beforeDestroy', () => {
                cleanWindowResize();
                this.firework?.clear?.();
                this.firework = null;
            });
        },

        methods: {
            async setStore() {
                if (typeof this.getConfig !== 'function') return;

                const config = await this.getConfig();
                const {
                    DateRange = '',
                    Perday = DefaultPerday,
                    IsOn = false
                } = this.serializer ? _.get(config, this.serializer, Object.create(null)) : config;

                if (!IsOn) {
                    set(store, null);

                    return;
                }

                const dateRange = DateRange
                    ?.split(',')
                    ?.slice(0, 2)
                    ?.map((date, index) => moment(date)?.[index ? 'endOf' : 'startOf']?.('day'))
                    ?.filter(date => date?.isValid?.())
                    ?? [];

                const {perDay: cachePerday, expired: cacheExpired} = get(store) ?? {};
                const isExpired = cacheExpired === true || moment().isAfter(cacheExpired);
                const perDay = isExpired
                    ? Number(Perday) || DefaultPerday
                    : cachePerday;

                set(store, {
                    perDay,
                    dateRange,
                    expired: moment().endOf('day')
                });
            },

            checkCanFire() {
                const {perDay, dateRange} = get(store) ?? {};
                const now = moment();

                const canFire = dateRange?.length === 2
                    && now.isAfter(dateRange?.[0])
                    && now.isBefore(dateRange?.[1])
                    && !Number.isNaN(perDay)
                    && perDay > 0;

                return canFire;
            },

            updateCanvasSize() {
                if (!this.firework) return;

                const {width, height} = useWindowSize();
                this.firework.updateSize?.({width: get(width), height: get(height)});
            },

            async launch(afterLaunchCb) {
                for (let index = 0; index < this.launchCount; index++) {
                    await promiseTimeout(this.intervalPerLaunch);

                    this.firework?.launch?.(this.countPerLaunch);
                }

                await promiseTimeout(2000);

                afterLaunchCb?.();
            }
        },

        render() {
            return (
                <div class="firework-container" style={this.style} ref="container" />
            );
        }
    };

</script>
