// The increased timeout is especially needed with larger binaries
// like in the debug/gpu build
jasmine.DEFAULT_TIMEOUT_INTERVAL = 20000;

describe('CanvasKit\'s Animation', function() {
    // Note, don't try to print the CanvasKit object - it can cause Karma/Jasmine to lock up.
    var CanvasKit = null;
    const LoadCanvasKit = new Promise(function(resolve, reject) {
        if (CanvasKit) {
            resolve();
        } else {
            CanvasKitInit({
                locateFile: (file) => '/canvaskit/'+file,
            }).ready().then((_CanvasKit) => {
                CanvasKit = _CanvasKit;
                resolve();
            });
        }
    });

    const LOTTIE_ANIMATIONS = ['lego_loader', 'drinks', 'confetti', 'onboarding'];

    let container = document.createElement('div');
    document.body.appendChild(container);


    beforeEach(function() {
        container.innerHTML = `
            <canvas width=600 height=600 id=test></canvas>`;
    });

    afterEach(function() {
        container.innerHTML = '';
    });

    function fetchAndText(url) {
        return new Promise(function(resolve, reject) {
            fetch(url).then((resp) => {
                    resp.text().then((str) => {
                        expect(str).toBeTruthy();
                        resolve(str);
                    });
                }).catch(reject);
        });
    }

    LOTTIE_ANIMATIONS.forEach((animStr) => {
        let promises = [fetchAndText(`/assets/${animStr}.json`), LoadCanvasKit];

        it(`animation loading for ${animStr}`, function(done) {
            let jsonStr = '';
            function setup(ctx) {
                expect(jsonStr).toBeTruthy();
            }

            function test(ctx) {
                const animation = CanvasKit.MakeAnimation(jsonStr);
                animation.delete();
            }

            function teardown(ctx) {}

            Promise.all(promises).then((responses) => {
                // The result from the first promise, that is, the JSON string
                // fetched by fetchAndText
                jsonStr = responses[0];
                benchmarkAndReport(`${animStr}_animation_load`, setup, test, teardown).then(() => {
                    done();
                }).catch(reportError(done));
            });
        });

        it(`animation frames in order for ${animStr}`, function(done) {
            let jsonStr = '';
            function setup(ctx) {
                expect(jsonStr).toBeTruthy();
                ctx.animation = CanvasKit.MakeAnimation(jsonStr);
                expect(ctx.animation).toBeTruthy();
                ctx.timer = 0;
            }

            function test(ctx) {
                ctx.animation.seek(ctx.timer);
                ctx.timer += 0.01;
                if (ctx.timer > 1.0) {
                    ctx.timer = 0;
                }
            }

            function teardown(ctx) {
                ctx.animation.delete();
            }

            Promise.all(promises).then((responses) => {
                // The result from the first promise, that is, the JSON string
                // fetched by fetchAndText
                jsonStr = responses[0];
                benchmarkAndReport(`${animStr}_animation_in_order`, setup, test, teardown).then(() => {
                    done();
                }).catch(reportError(done));
            });
        });

        it(`animation frames in random order for ${animStr}`, function(done) {
            let jsonStr = '';
            function setup(ctx) {
                expect(jsonStr).toBeTruthy();
                ctx.animation = CanvasKit.MakeAnimation(jsonStr);
                expect(ctx.animation).toBeTruthy();
            }

            function test(ctx) {
                ctx.animation.seek(Math.random());
            }

            function teardown(ctx) {
                ctx.animation.delete();
            }

            Promise.all(promises).then((responses) => {
                // The result from the first promise, that is, the JSON string
                // fetched by fetchAndText
                jsonStr = responses[0];
                benchmarkAndReport(`${animStr}_animation_random_order`, setup, test, teardown).then(() => {
                    done();
                }).catch(reportError(done));
            });
        });

        it(`renders to an HTML canvas ${animStr}`, function(done) {
            let jsonStr = '';
            function setup(ctx) {
                expect(jsonStr).toBeTruthy();
                ctx.animation = CanvasKit.MakeAnimation(jsonStr);
                expect(ctx.animation).toBeTruthy();
                ctx.animation.seek(0.5);
                ctx.surface = CanvasKit.MakeCanvasSurface('test');
                ctx.canvas = ctx.surface.getCanvas();
                ctx.clear = CanvasKit.Color(255, 255, 255, 0.0); // transparent
            }

            function test(ctx) {
                // This emulates what would need to be done do accurately
                // draw one frame.
                ctx.canvas.clear(ctx.clear);
                ctx.animation.render(ctx.canvas);
                ctx.surface.flush();
            }

            function teardown(ctx) {
                ctx.animation.delete();
                ctx.surface.dispose(); // ctx.canvas will also be cleaned up
            }

            Promise.all(promises).then((responses) => {
                // The result from the first promise, that is, the JSON string
                // fetched by fetchAndText
                jsonStr = responses[0];
                benchmarkAndReport(`${animStr}_animation_render_flush`, setup, test, teardown).then(() => {
                    done();
                }).catch(reportError(done));
            });
        });

    });

});