import {GifReader} from 'omggif';

export default (arrayBuffer, onFrame) => {
    const canvas = document.createElement('canvas');
    const ctx = canvas.getContext('2d');
    const gifReader = new GifReader(new Uint8Array(arrayBuffer));
    const numFrames = gifReader.numFrames();
    canvas.width = gifReader.width;
    canvas.height = gifReader.height;

    let imageData = ctx.createImageData(canvas.width, canvas.height);
    let previousData = ctx.createImageData(canvas.width, canvas.height);

    const loadFrame = i => {
        const framePixels = [];
        gifReader.decodeAndBlitFrameRGBA(i, framePixels);
        const {x, y, width, height, disposal} = gifReader.frameInfo(i);
        for (let row = 0; row < height; row++) {
            for (let column = 0; column < width; column++) {
                const indexOffset = 4 * (x + (y * canvas.width));
                const j = indexOffset + (4 * (column + (row * canvas.width)));
                if (framePixels[j + 3]) {
                    imageData.data[j + 0] = framePixels[j + 0];
                    imageData.data[j + 1] = framePixels[j + 1];
                    imageData.data[j + 2] = framePixels[j + 2];
                    imageData.data[j + 3] = framePixels[j + 3];
                }
            }
        }

        ctx.clearRect(0, 0, canvas.width, canvas.height);
        ctx.putImageData(imageData, 0, 0);

        const dataUrl = canvas.toDataURL();

        switch (disposal) {
        case 2: // "Return to background", blank out the current frame
            ctx.clearRect(x, y, width, height);
            imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
            break;
        case 3: // "Restore to previous", copy previous data to current
            imageData = ctx.createImageData(canvas.width, canvas.height);
            imageData.data.set(previousData.data);
            break;
        default: // 0 and 1, as well as 4+ modes = do-not-dispose, so cache frame
            previousData = ctx.getImageData(0, 0, canvas.width, canvas.height);
            break;

        }
        onFrame(i, dataUrl, numFrames);

        if (i < numFrames - 1) {
            setTimeout(() => {
                loadFrame(i + 1);
            });
        }
    };

    loadFrame(0);
};