import { describe, it, expect } from 'vitest';
import { Shake } from '../shake';

describe('Shake', () => {
    it('неактивен без толчков, offset нулевой', () => {
        const s = new Shake();
        expect(s.active).toBe(false);
        expect(s.offset).toEqual({ x: 0, y: 0 });
    });

    it('толчок с нулевой/отрицательной силой игнорируется', () => {
        const s = new Shake();
        s.add(0, 1);
        s.add(5, 0);
        s.add(-3, 1);
        expect(s.active).toBe(false);
    });

    it('активен во время действия и выключается по окончании', () => {
        const s = new Shake();
        s.add(4, 0.5);
        expect(s.active).toBe(true);
        s.update(0.3);
        expect(s.active).toBe(true);
        s.update(0.3);
        expect(s.active).toBe(false);
        expect(s.offset).toEqual({ x: 0, y: 0 });
    });

    it('амплитуда не превышает силу толчка и затухает', () => {
        const s = new Shake(42);
        s.add(6, 1);
        let maxAbs = 0;
        for (let i = 0; i < 60; i++) {
            s.update(1 / 60);
            const { x, y } = s.offset;
            expect(Math.abs(x)).toBeLessThanOrEqual(6);
            expect(Math.abs(y)).toBeLessThanOrEqual(6);
            maxAbs = Math.max(maxAbs, Math.abs(x));
        }
        // в какой-то из ранних кадров смещение ощутимо
        expect(maxAbs).toBeGreaterThan(0);
    });

    it('одинаковый seed — одинаковые смещения', () => {
        const a = new Shake(7);
        const b = new Shake(7);
        a.add(5, 0.3);
        b.add(5, 0.3);
        for (let i = 0; i < 20; i++) {
            a.update(1 / 60);
            b.update(1 / 60);
            expect(a.offset).toEqual(b.offset);
        }
    });

    it('offset округляется до целых пикселей', () => {
        const s = new Shake(1);
        s.add(0.5, 0.1);
        s.update(1 / 120);
        const { x, y } = s.offset;
        expect(Number.isInteger(x)).toBe(true);
        expect(Number.isInteger(y)).toBe(true);
    });

    it('два толчка складываются, clear сбрасывает', () => {
        const s = new Shake(9);
        s.add(3, 1);
        s.add(3, 1);
        s.update(0.1);
        expect(s.active).toBe(true);
        s.clear();
        expect(s.active).toBe(false);
        expect(s.offset).toEqual({ x: 0, y: 0 });
    });
});