class Wiggler {
    constructor(canvas, target) {
        console.log("start init")

        this.canvas = canvas;
        this.ctx = canvas.getContext("2d");

        this.width = this.canvas.width;
        this.height = this.canvas.height;

        let maxx = Math.max(...target.flatMap(l => l.map(k => k[0])));
        let maxy = Math.max(...target.flatMap(l => l.map(k => k[1])))

        let offsx = (this.width - maxx) / 2
        let offsy = (this.height - maxy) / 2

        this.target = target.map(c => c.map(l => [l[0] + offsx, l[1] + offsy]));

        // this.initRandom();
        // this.initCorners();
        this.current = this.initEdges(maxx, maxy);
    }

    initRandom() {
        return this.target.map(l => {
            const px = Math.random() * this.width;
            const py = Math.random() * this.height;
            const r = Math.PI * 2;
            const tx = px + Math.cos(r) * 10;
            const ty = py + Math.sin(r) * 10;

            return [[px, py], [tx, ty]];
        });
    }

    initCorners() {
        return this.target.map(l => {
            const px = Math.random() < .5 ? 0 : this.width;
            const py = Math.random() < .5 ? 0 : this.height;
            const r = Math.PI * 2;
            const tx = px + Math.cos(r) * 10;
            const ty = py + Math.sin(r) * 10;

            return [[px, py], [tx, ty]];
        });
    }

    initEdges() {
        return this.target.map(() => {
            var px, py;
            if (Math.random() < .5) {
                px = Math.random() < .5 ? 0 : this.width;
                py = Math.random() * this.height;
            } else {
                px = Math.random() * this.width;
                py = Math.random() < .5 ? 0 : this.height;
            }
            return [[px, py], [px, py]];
        });
    }

    start() {
        console.log("start");
        if (!this.running) {
            this.running = true;
            this.animate();
        }
    }

    stop() {
        console.log("stop");
        if (this.running) {
            this.running = false;
        }
    }

    toggle() {
        this.running = !this.running;
        if (this.running) {
            this.animate();
        } else {
            console.log("stop");
        }
    }

    animate() {
        if (this.running) {
            this.update();
            this.draw();
            window.requestAnimationFrame(() => { this.animate(); })
        }
    }

    dist(p1, p2) {
        const dx = p1[0] - p2[0];
        const dy = p1[1] - p2[1];
        return Math.sqrt(dx * dx + dy * dy);
    }

    mv(d) { return Math.random() * d - (d / 2.0); }

    update() {
        var changed = false;

        for (var l = 0; l < this.current.length; l++) {
            for (var p = 0; p < 2; p++) {
                const cp = this.current[l][p];
                const tp = this.target[l][p];

                if (this.dist(cp, tp) > .5) {
                    changed = true;
                    const dist = this.dist(cp, tp);
                    var np;
                    var ndist;

                    do {
                        const dx = this.mv(Math.sqrt(dist) + 2);
                        const dy = this.mv(Math.sqrt(dist) + 2);
                        np = [cp[0] + dx, cp[1] + dy];
                        ndist = this.dist(np, tp);
                    } while (ndist > dist);

                    this.current[l][p] = np;

                }
            }
        }

        if (!changed) {
            this.running = false;
        }
    }

    draw() {
        this.fillStyle = "#C9E6F0"
        this.ctx.clearRect(0, 0, 800, 600)

        this.ctx.strokeStyle = "white"
        this.ctx.lineWidth = 3
        this.ctx.lineJoin = "round"
        this.ctx.lineCap = "round"

        this.current.forEach(l => {
            this.ctx.beginPath()
            this.ctx.moveTo(l[0][0], l[0][1])
            this.ctx.lineTo(l[1][0], l[1][1])
            this.ctx.stroke()
        });
    }

    mash() {
        // replace target lines randomly
        for (let i = 0; i < this.target.length; i++) {
            let c0, c1;
            do {
                c0 = i
                c1 = Math.floor(Math.random() * this.target.length)
            } while (c0 == c1);

            let l0 = this.target[c0][0]
            let l1 = this.target[c0][1]

            this.target[c0][0] = this.target[c1][0]
            this.target[c0][1] = this.target[c1][1]

            this.target[c1][0] = l0
            this.target[c1][1] = l1
        }

        if (!this.running) {
            this.running = true;
            this.animate();
        }
    }
}

Array.__prototype

const textToCoords = (text, scale, alphabet) => {
    var base = 0;

    var output = Array.from(text).flatMap(c => {
        const g = alphabet[c].map(l =>
            l.map(p => [p[0] * scale + base, p[1] * scale])
        );

        const maxx = alphabet[c].map(l => Math.max(l[0][0], l[1][0]));

        // width of character plus
        const inc = (Math.max(1, Math.max(...maxx)) + 0.2) * scale;
        base += inc;

        return g;
    });

    return output;
};

document.addEventListener('DOMContentLoaded', () => {
    console.log("kleines büro ready ...");

    const canvas = document.getElementById("banner");
    const target = textToCoords("KLEINES BÜRO", 20, alphabet);
    const wiggler = new Wiggler(canvas, target);

    wiggler.start();

    canvas.addEventListener("click", () => { wiggler.mash(); });

    new Splide('.splide', {
        padding: '5rem',
    }).mount();

});