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

#include "tests/Test.h"

#include "include/core/SkMallocPixelRef.h"
#include "include/core/SkPixelRef.h"

static void decrement_counter_proc(void* pixels, void* ctx) {
    int* counter = (int*)ctx;
    *counter -= 1;
}

static void test_dont_leak_install(skiatest::Reporter* reporter) {
    bool success;
    int release_counter;
    SkImageInfo info;
    SkBitmap bm;

    info = SkImageInfo::MakeN32Premul(0, 0);
    release_counter = 1;
    success = bm.installPixels(info, nullptr, 0, decrement_counter_proc, &release_counter);
    REPORTER_ASSERT(reporter, true == success);
    bm.reset();
    REPORTER_ASSERT(reporter, 0 == release_counter);

    info = SkImageInfo::MakeN32Premul(10, 10);
    release_counter = 1;
    success = bm.installPixels(info, nullptr, 0, decrement_counter_proc, &release_counter);
    REPORTER_ASSERT(reporter, true == success);
    bm.reset();
    REPORTER_ASSERT(reporter, 0 == release_counter);

    info = SkImageInfo::MakeN32Premul(-10, -10);
    release_counter = 1;
    success = bm.installPixels(info, nullptr, 0, decrement_counter_proc, &release_counter);
    REPORTER_ASSERT(reporter, false == success);
    bm.reset();
    REPORTER_ASSERT(reporter, 0 == release_counter);
}

static void test_install(skiatest::Reporter* reporter) {
    bool success;
    SkImageInfo info = SkImageInfo::MakeN32Premul(0, 0);
    SkBitmap bm;
    // make sure we don't assert on an empty install
    success = bm.installPixels(info, nullptr, 0);
    REPORTER_ASSERT(reporter, success);

    // no pixels should be the same as setInfo()
    info = SkImageInfo::MakeN32Premul(10, 10);
    success = bm.installPixels(info, nullptr, 0);
    REPORTER_ASSERT(reporter, success);

}

class TestListener : public SkPixelRef::GenIDChangeListener {
public:
    explicit TestListener(int* ptr) : fPtr(ptr) {}
    void onChange() override { (*fPtr)++; }
private:
    int* fPtr;
};

DEF_TEST(PixelRef_GenIDChange, r) {
    SkImageInfo info = SkImageInfo::MakeN32Premul(10, 10);

    sk_sp<SkPixelRef> pixelRef = SkMallocPixelRef::MakeAllocate(info, 0);

    // Register a listener.
    int count = 0;
    pixelRef->addGenIDChangeListener(new TestListener(&count));
    REPORTER_ASSERT(r, 0 == count);

    // No one has looked at our pixelRef's generation ID, so invalidating it doesn't make sense.
    // (An SkPixelRef tree falls in the forest but there's nobody around to hear it.  Do we care?)
    pixelRef->notifyPixelsChanged();
    REPORTER_ASSERT(r, 0 == count);

    // Force the generation ID to be calculated.
    REPORTER_ASSERT(r, 0 != pixelRef->getGenerationID());

    // Our listener was dropped in the first call to notifyPixelsChanged().  This is a no-op.
    pixelRef->notifyPixelsChanged();
    REPORTER_ASSERT(r, 0 == count);

    // Force the generation ID to be recalculated, then add a listener.
    REPORTER_ASSERT(r, 0 != pixelRef->getGenerationID());
    pixelRef->addGenIDChangeListener(new TestListener(&count));
    pixelRef->notifyPixelsChanged();
    REPORTER_ASSERT(r, 1 == count);

    // Quick check that nullptr is safe.
    REPORTER_ASSERT(r, 0 != pixelRef->getGenerationID());
    pixelRef->addGenIDChangeListener(nullptr);
    pixelRef->notifyPixelsChanged();

    test_install(r);
    test_dont_leak_install(r);
}
