/*
 * Copyright 2018 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "CodecPriv.h"
#include "Resources.h"
#include "SkAndroidCodec.h"
#include "SkAnimatedImage.h"
#include "SkBitmap.h"
#include "SkCanvas.h"
#include "SkCodec.h"
#include "SkColor.h"
#include "SkData.h"
#include "SkImageInfo.h"
#include "SkPicture.h"
#include "SkRefCnt.h"
#include "SkSize.h"
#include "SkString.h"
#include "SkTypes.h"
#include "SkUnPreMultiply.h"
#include "Test.h"
#include "sk_tool_utils.h"

#include <algorithm>
#include <memory>
#include <vector>

DEF_TEST(AnimatedImage_scaled, r) {
    if (GetResourcePath().isEmpty()) {
        return;
    }

    const char* file = "images/alphabetAnim.gif";
    auto data = GetResourceAsData(file);
    if (!data) {
        ERRORF(r, "Could not get %s", file);
        return;
    }

    auto codec = SkAndroidCodec::MakeFromCodec(SkCodec::MakeFromData(data));
    if (!codec) {
        ERRORF(r, "Could not create codec for %s", file);
        return;
    }

    // Force the drawable follow its special case that requires scaling.
    auto size = codec->getInfo().dimensions();
    size.set(size.width() - 5, size.height() - 5);
    auto rect = SkIRect::MakeSize(size);
    auto image = SkAnimatedImage::Make(std::move(codec), size, rect, nullptr);
    if (!image) {
        ERRORF(r, "Failed to create animated image for %s", file);
        return;
    }

    // Clear a bitmap to non-transparent and draw to it. pixels that are transparent
    // in the image should not replace the original non-transparent color.
    SkBitmap bm;
    bm.allocPixels(SkImageInfo::MakeN32Premul(size.width(), size.height()));
    bm.eraseColor(SK_ColorBLUE);
    SkCanvas canvas(bm);
    image->draw(&canvas);
    for (int i = 0; i < size.width();  ++i)
    for (int j = 0; j < size.height(); ++j) {
        if (*bm.getAddr32(i, j) == SK_ColorTRANSPARENT) {
            ERRORF(r, "Erased color underneath!");
            return;
        }
    }
}

static bool compare_bitmaps(skiatest::Reporter* r,
                            const char* file,
                            int expectedFrame,
                            const SkBitmap& expectedBm,
                            const SkBitmap& actualBm) {
    REPORTER_ASSERT(r, expectedBm.colorType() == actualBm.colorType());
    REPORTER_ASSERT(r, expectedBm.dimensions() == actualBm.dimensions());
    for (int i = 0; i < actualBm.width();  ++i)
    for (int j = 0; j < actualBm.height(); ++j) {
        SkColor expected = SkUnPreMultiply::PMColorToColor(*expectedBm.getAddr32(i, j));
        SkColor actual   = SkUnPreMultiply::PMColorToColor(*actualBm  .getAddr32(i, j));
        if (expected != actual) {
            ERRORF(r, "frame %i of %s does not match at pixel %i, %i!"
                            " expected %x\tactual: %x",
                            expectedFrame, file, i, j, expected, actual);
            SkString expected_name = SkStringPrintf("expected_%c", '0' + expectedFrame);
            SkString actual_name   = SkStringPrintf("actual_%c",   '0' + expectedFrame);
            write_bm(expected_name.c_str(), expectedBm);
            write_bm(actual_name.c_str(),   actualBm);
            return false;
        }
    }
    return true;
}

// Temporary hack to avoid linear sRGB 8888 surfaces.
static SkImageInfo temporarily_sanitize(SkImageInfo info) {
    if (info.colorType() == kRGBA_8888_SkColorType ||
        info.colorType() == kBGRA_8888_SkColorType) {
        if (info.colorSpace() && info.colorSpace()->isSRGB()) {
            info = info.makeColorSpace(nullptr);
        }
    }
    return info;
}

DEF_TEST(AnimatedImage_copyOnWrite, r) {
    if (GetResourcePath().isEmpty()) {
        return;
    }
    for (const char* file : { "images/alphabetAnim.gif",
                              "images/colorTables.gif",
                              "images/webp-animated.webp",
                              "images/required.webp",
                              }) {
        auto data = GetResourceAsData(file);
        if (!data) {
            ERRORF(r, "Could not get %s", file);
            continue;
        }

        auto codec = SkCodec::MakeFromData(data);
        if (!codec) {
            ERRORF(r, "Could not create codec for %s", file);
            continue;
        }

        const auto imageInfo = codec->getInfo().makeAlphaType(kPremul_SkAlphaType);
        const int frameCount = codec->getFrameCount();
        auto androidCodec = SkAndroidCodec::MakeFromCodec(std::move(codec));
        if (!androidCodec) {
            ERRORF(r, "Could not create androidCodec for %s", file);
            continue;
        }

        auto animatedImage = SkAnimatedImage::Make(std::move(androidCodec));
        if (!animatedImage) {
            ERRORF(r, "Could not create animated image for %s", file);
            continue;
        }
        animatedImage->setRepetitionCount(0);

        std::vector<SkBitmap> expected(frameCount);
        std::vector<sk_sp<SkPicture>> pictures(frameCount);
        for (int i = 0; i < frameCount; i++) {
            SkBitmap& bm = expected[i];
            bm.allocPixels(temporarily_sanitize(imageInfo));
            bm.eraseColor(SK_ColorTRANSPARENT);
            SkCanvas canvas(bm);

            pictures[i].reset(animatedImage->newPictureSnapshot());
            canvas.drawPicture(pictures[i]);

            const auto duration = animatedImage->decodeNextFrame();
            // We're attempting to decode i + 1, so decodeNextFrame will return
            // kFinished if that is the last frame (or we attempt to decode one
            // more).
            if (i >= frameCount - 2) {
                REPORTER_ASSERT(r, duration == SkAnimatedImage::kFinished);
            } else {
                REPORTER_ASSERT(r, duration != SkAnimatedImage::kFinished);
            }
        }

        for (int i = 0; i < frameCount; i++) {
            SkBitmap test;
            test.allocPixels(temporarily_sanitize(imageInfo));
            test.eraseColor(SK_ColorTRANSPARENT);
            SkCanvas canvas(test);

            canvas.drawPicture(pictures[i]);

            compare_bitmaps(r, file, i, expected[i], test);
        }
    }
}

DEF_TEST(AnimatedImage, r) {
    if (GetResourcePath().isEmpty()) {
        return;
    }
    for (const char* file : { "images/alphabetAnim.gif",
                              "images/colorTables.gif",
                              "images/webp-animated.webp",
                              "images/required.webp",
                              }) {
        auto data = GetResourceAsData(file);
        if (!data) {
            ERRORF(r, "Could not get %s", file);
            continue;
        }

        auto codec = SkCodec::MakeFromData(data);
        if (!codec) {
            ERRORF(r, "Could not create codec for %s", file);
            continue;
        }

        const int defaultRepetitionCount = codec->getRepetitionCount();
        std::vector<SkCodec::FrameInfo> frameInfos = codec->getFrameInfo();
        std::vector<SkBitmap> frames(frameInfos.size());
        // Used down below for our test image.
        const auto imageInfo = codec->getInfo().makeAlphaType(kPremul_SkAlphaType);

        for (size_t i = 0; i < frameInfos.size(); ++i) {
            auto info = codec->getInfo().makeAlphaType(frameInfos[i].fAlphaType);
            auto& bm = frames[i];

            SkCodec::Options options;
            options.fFrameIndex = (int) i;
            options.fPriorFrame = frameInfos[i].fRequiredFrame;
            if (options.fPriorFrame == SkCodec::kNone) {
                bm.allocPixels(info);
                bm.eraseColor(0);
            } else {
                const SkBitmap& priorFrame = frames[options.fPriorFrame];
                if (!sk_tool_utils::copy_to(&bm, priorFrame.colorType(), priorFrame)) {
                    ERRORF(r, "Failed to copy %s frame %i", file, options.fPriorFrame);
                    options.fPriorFrame = SkCodec::kNone;
                }
                REPORTER_ASSERT(r, bm.setAlphaType(frameInfos[i].fAlphaType));
            }

            auto result = codec->getPixels(info, bm.getPixels(), bm.rowBytes(), &options);
            if (result != SkCodec::kSuccess) {
                ERRORF(r, "error in %s frame %zu: %s", file, i, SkCodec::ResultToString(result));
            }
        }

        auto androidCodec = SkAndroidCodec::MakeFromCodec(std::move(codec));
        if (!androidCodec) {
            ERRORF(r, "Could not create androidCodec for %s", file);
            continue;
        }

        auto animatedImage = SkAnimatedImage::Make(std::move(androidCodec));
        if (!animatedImage) {
            ERRORF(r, "Could not create animated image for %s", file);
            continue;
        }

        REPORTER_ASSERT(r, defaultRepetitionCount == animatedImage->getRepetitionCount());

        auto testDraw = [r, &frames, &imageInfo, file](const sk_sp<SkAnimatedImage>& animatedImage,
                                                       int expectedFrame) {
            SkBitmap test;
            test.allocPixels(temporarily_sanitize(imageInfo));
            test.eraseColor(0);
            SkCanvas c(test);
            animatedImage->draw(&c);

            const SkBitmap& frame = frames[expectedFrame];
            return compare_bitmaps(r, file, expectedFrame, frame, test);
        };

        REPORTER_ASSERT(r, animatedImage->currentFrameDuration() == frameInfos[0].fDuration);

        if (!testDraw(animatedImage, 0)) {
            ERRORF(r, "Did not start with frame 0");
            continue;
        }

        // Start at an arbitrary time.
        bool failed = false;
        for (size_t i = 1; i < frameInfos.size(); ++i) {
            const int frameTime = animatedImage->decodeNextFrame();
            REPORTER_ASSERT(r, frameTime == animatedImage->currentFrameDuration());

            if (i == frameInfos.size() - 1 && defaultRepetitionCount == 0) {
                REPORTER_ASSERT(r, frameTime == SkAnimatedImage::kFinished);
                REPORTER_ASSERT(r, animatedImage->isFinished());
            } else {
                REPORTER_ASSERT(r, frameTime == frameInfos[i].fDuration);
                REPORTER_ASSERT(r, !animatedImage->isFinished());
            }

            if (!testDraw(animatedImage, i)) {
                ERRORF(r, "Did not update to %i properly", i);
                failed = true;
                break;
            }
        }

        if (failed) {
            continue;
        }

        animatedImage->reset();
        REPORTER_ASSERT(r, !animatedImage->isFinished());
        if (!testDraw(animatedImage, 0)) {
            ERRORF(r, "reset failed");
            continue;
        }

        // Test reset from all the frames.
        // j is the frame to call reset on.
        for (int j = 0; j < (int) frameInfos.size(); ++j) {
            if (failed) {
                break;
            }

            // i is the frame to decode.
            for (int i = 0; i <= j; ++i) {
                if (i == j) {
                    animatedImage->reset();
                    if (!testDraw(animatedImage, 0)) {
                        ERRORF(r, "reset failed for image %s from frame %i",
                                file, i);
                        failed = true;
                        break;
                    }
                } else if (i != 0) {
                    animatedImage->decodeNextFrame();
                    if (!testDraw(animatedImage, i)) {
                        ERRORF(r, "failed to match frame %i in %s on iteration %i",
                                i, file, j);
                        failed = true;
                        break;
                    }
                }
            }
        }

        if (failed) {
            continue;
        }

        for (int loopCount : { 0, 1, 2, 5 }) {
            animatedImage = SkAnimatedImage::Make(SkAndroidCodec::MakeFromCodec(
                        SkCodec::MakeFromData(data)));
            animatedImage->setRepetitionCount(loopCount);
            REPORTER_ASSERT(r, animatedImage->getRepetitionCount() == loopCount);

            for (int loops = 0; loops <= loopCount; loops++) {
                if (failed) {
                    break;
                }
                REPORTER_ASSERT(r, !animatedImage->isFinished());
                for (size_t i = 1; i <= frameInfos.size(); ++i) {
                    const int frameTime = animatedImage->decodeNextFrame();
                    if (frameTime == SkAnimatedImage::kFinished) {
                        if (loops != loopCount) {
                            ERRORF(r, "%s animation stopped early: loops: %i\tloopCount: %i",
                                    file, loops, loopCount);
                            failed = true;
                        }
                        if (i != frameInfos.size() - 1) {
                            ERRORF(r, "%s animation stopped early: i: %i\tsize: %i",
                                    file, i, frameInfos.size());
                            failed = true;
                        }
                        break;
                    }
                }
            }

            if (!animatedImage->isFinished()) {
                ERRORF(r, "%s animation should have finished with specified loop count (%i)",
                          file, loopCount);
            }
        }
    }
}
