import * as d3 from 'd3';

let PluseIDCount = 0;

export class PulseLine {
    constructor() {
        this.animation = undefined;
        this.pluseId = undefined;
    }

    /**
     * 
     * @param {d3.Selection} parentSelection 
     */
    loadToSelection(parentSelection, data) {
        this.pluseId = data.id;
        
        const gId = 'pluse-g' + data.id;
        const pId = 'pluse-p' + data.id;
        const mId = 'pluse-m' + data.id;
        const uId = 'pluse-u' + data.id;

        const g = parentSelection.append("g")
            .attr("mask", `url(#${mId})`);
        
        this.g = g;

        // 创建 mask
        const mask = parentSelection.append("mask")
            .attr('id', mId);
        
        this.mask = mask;

        const maskPathSelection = mask.append("use")
            .attr("id", uId)
            .attr("href", "#" + pId)
            .attr("stroke", "white")
            .attr("stroke-width", 7)
            .attr("fill", "none")
            .attr('stroke-dasharray', '200 300')
            .attr("stroke-linecap", "round");
        
        this.maskPathSelection = maskPathSelection;

        // 创建 radialGradient
        const radialGradient = g.append("radialGradient")
            .attr("id", gId);
        
        radialGradient.append("stop")
            .attr("offset", "0%")
            .attr("stop-color", "white");
        
        radialGradient.append("stop")
            .attr("offset", "25%")
            .attr("stop-color", "#CB81DA");
        
        radialGradient.append("stop")
            .attr("offset", "95%")
            .attr("stop-opacity", 0)
            .attr("stop-color", "rgb(70, 70, 222)");
        
        // 创建 path
        const pathSelection = g.append("path")
            .attr("id", pId)
            .attr('stroke-width', 10)
            .attr("fill", "none")
            .attr("d", data.svg);
        
        this.pathSelection = pathSelection;

        // 创建 circle 和 animateMotion
        g.append("circle")
            .attr("r", 100)
            .attr("fill", `url(#${gId})`)
            .append("animateMotion")
            .attr("dur", "3000ms")
            .attr("repeatCount", "indefinite")
            .append("mpath")
            .attr("href", "#" + pId);
    }

    startAnimation() {
        if (this.animation) {
            requestAnimationFrame(() => {
                const motionElement = this.g.selectAll('animateMotion').node();
                motionElement.setAttribute('begin', '0s');
                motionElement.beginElement();
                this.animation.play();
            });
        } else {    
            const pathElement = this.pathSelection.node();
            const pluseElement = this.maskPathSelection.node();
    
            const pathLength = pathElement.getTotalLength();
            
            // 600 配合 3000 比较合适
            const v = 0.5;
            const duration = pathLength / v;
    
            const keyframes = new KeyframeEffect(
                pluseElement, [{
                    strokeDasharray: `200 ${pathLength - 200}`,
                    strokeDashoffset: "200"
                },
                {
                    strokeDasharray: `200 ${pathLength}`,
                    strokeDashoffset: `-${pathLength - 200}`
                }
            ], {
                duration: duration,
                iterations: Infinity
            }
            );
    
            const pulsationAnimation = new Animation(keyframes, document.timeline);
            this.animation = pulsationAnimation;

            requestAnimationFrame(() => {
                const motionElement = this.g.selectAll('animateMotion').node();
                motionElement.setAttribute('begin', '0s');
                motionElement.setAttribute('dur', duration + 'ms');
                motionElement.beginElement();
                pulsationAnimation.currentTime = 0;
                pulsationAnimation.play();
            });
        }
    }

    pauseAnimation() {
        if (!this.animation) {
            return;
        }
        this.animation.pause();
    }

    destory() {
        if (this.g) {
            this.g.remove();
        }
        if (this.mask) {
            this.mask.remove();
        }
    }
}

/**
 * @typedef PulseLineSvgConfig
 * @property {string} pluseStartColor
 * @property {string} pluseMiddleColor
 * @property {string} pluseEndColor
 * @property {string} transform
 * @property {number} duration
 */