import anime from 'animejs';
import TrailImage from './TrailImage';

// body element
const body = document.body;

// helper functions
const MathUtils = {
    // linear interpolation
    lerp: (a, b, n) => (1 - n) * a + n * b,
    // distance between two points
    distance: (x1,y1,x2,y2) => Math.hypot(x2-x1, y2-y1)
}

// get the mouse position
const getMousePos = (ev) => {
    let posx = 0;
    let posy = 0;
    if (!ev) ev = window.event;
    if (ev.pageX || ev.pageY) {
        posx = ev.pageX;
        posy = ev.pageY;
    }
    else if (ev.clientX || ev.clientY) 	{
        posx = ev.clientX + body.scrollLeft + docEl.scrollLeft;
        posy = ev.clientY + body.scrollTop + docEl.scrollTop;
    }
    return {x: posx, y: posy};
}

// mousePos: current mouse position
// cacheMousePos: previous mouse position
// lastMousePos: last last recorded mouse position (at the time the last image was shown)
let mousePos = {x: 0, y: 0};
let lastMousePos = {x: 0, y: 0};
let cacheMousePos = {x: 0, y: 0};

// update the mouse position
window.addEventListener('mousemove', ev => mousePos = getMousePos(ev));

// gets the distance from the current mouse position to the last recorded mouse position
const getMouseDistance = () => MathUtils.distance(mousePos.x,mousePos.y,lastMousePos.x,lastMousePos.y);

class TrailEffect {
    constructor() {
        this.images = [];
        [...document.querySelectorAll('.trailImg')].forEach(img => this.images.push(new TrailImage(img)));
        this.imagesTotal = this.images.length;
        this.imgPosition = 0;
        this.zIndexVal = 1;
        this.threshold = 150;
        requestAnimationFrame(() => this.render());
    }
    render() {
        let distance = getMouseDistance();
        cacheMousePos.x = MathUtils.lerp(cacheMousePos.x || mousePos.x, mousePos.x, 0.1);
        cacheMousePos.y = MathUtils.lerp(cacheMousePos.y || mousePos.y, mousePos.y, 0.1);

        if ( distance > this.threshold ) {
            this.showNextImage();

            ++this.zIndexVal;
            this.imgPosition = this.imgPosition < this.imagesTotal-1 ? this.imgPosition+1 : 0;
            
            lastMousePos = mousePos;
        }

        let isIdle = true;
        for (let img of this.images) {
            if ( img.isActive() ) {
                isIdle = false;
                break;
            }
        }
        if ( isIdle && this.zIndexVal !== 1 ) {
            this.zIndexVal = 1;
        }

        requestAnimationFrame(() => this.render());
    }
    showNextImage() {
        const img = this.images[this.imgPosition];

        // // kill any tween on the image
        anime.remove(img.DOM.el);

        anime.timeline()
        .set(img.DOM.el, {
            zIndex: this.zIndexVal,
            translateX: cacheMousePos.x - img.rect.width/2,
            translateY: cacheMousePos.y - img.rect.height/2
        })
        .add({
            targets: img.DOM.el,
            duration: 1000,
            easing: 'easeOutExpo',
            zIndex: this.zIndexVal,
            scale: [0.4, 1],
            opacity: [0, 1],
            translateX: [cacheMousePos.x - img.rect.width/2, mousePos.x - img.rect.width/2],
            translateY: [cacheMousePos.y - img.rect.height/2, mousePos.y - img.rect.height/2]
        })
        .add({
            targets: img.DOM.el,
            duration: 600,
            easing: 'easeOutExpo',
            scale: [1, 0.4],
            opacity: [1, 0],
        }, '-=200');
    }
}

export default TrailEffect;