/*
 * Copyright 2022 Google LLC
 *
 * 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/SkBitmap.h"
#include "include/core/SkFont.h"
#include "include/gpu/graphite/Context.h"
#include "include/gpu/graphite/Recording.h"
#include "include/gpu/graphite/Surface.h"
#include "src/gpu/graphite/ContextPriv.h"
#include "src/gpu/graphite/Surface_Graphite.h"
#include "tests/TestUtils.h"
#include "tools/ToolUtils.h"
#include "tools/fonts/FontToolUtils.h"

using namespace skgpu::graphite;

namespace {

const SkISize kSurfaceSize = { 64, 64 };

constexpr SkColor4f kBackgroundColor = SkColors::kWhite;

bool run_test(skiatest::Reporter* reporter,
              Context* context,
              Recorder* recorder) {
    SkImageInfo ii = SkImageInfo::Make(kSurfaceSize, kRGBA_8888_SkColorType, kPremul_SkAlphaType);

    SkBitmap result0, result1;
    result0.allocPixels(ii);
    result1.allocPixels(ii);
    SkPixmap pm0, pm1;

    SkAssertResult(result0.peekPixels(&pm0));
    SkAssertResult(result1.peekPixels(&pm1));

    sk_sp<SkSurface> surface = SkSurfaces::RenderTarget(recorder, ii);
    if (!surface) {
        ERRORF(reporter, "Surface creation failed");
        return false;
    }

    SkCanvas* canvas = surface->getCanvas();

    // Set up a recording to clear the surface
    canvas->clear(kBackgroundColor);
    std::unique_ptr<Recording> clearRecording = recorder->snap();
    if (!clearRecording) {
        ERRORF(reporter, "Recording creation failed");
        return false;
    }

    // Draw some text and get recording
    SkPaint paint;
    paint.setAntiAlias(true);

    SkFont font(ToolUtils::CreatePortableTypeface("serif", SkFontStyle()));
    font.setSubpixel(true);
    font.setSize(12);

    const char* text0 = "Hamburge";
    const size_t text0Len = strlen(text0);

    canvas->drawSimpleText(text0, text0Len, SkTextEncoding::kUTF8, 3, 20, font, paint);
    std::unique_ptr<Recording> text0Recording = recorder->snap();

    // Draw some more text and get recording
    const char* text1 = "burgefons";
    const size_t text1Len = strlen(text1);

    canvas->drawSimpleText(text1, text1Len, SkTextEncoding::kUTF8, 3, 40, font, paint);
    std::unique_ptr<Recording> text1Recording = recorder->snap();

    // Playback 0, then 1, and read pixels
    InsertRecordingInfo info;
    info.fRecording = clearRecording.get();
    context->insertRecording(info);
    info.fRecording = text0Recording.get();
    context->insertRecording(info);
    info.fRecording = text1Recording.get();
    context->insertRecording(info);
    context->submit();

    if (!surface->readPixels(pm0, 0, 0)) {
        ERRORF(reporter, "readPixels failed");
        return false;
    }

    // Playback 1, then 0, and read pixels
    info.fRecording = clearRecording.get();
    context->insertRecording(info);
    info.fRecording = text1Recording.get();
    context->insertRecording(info);
    info.fRecording = text0Recording.get();
    context->insertRecording(info);
    context->submit();

    if (!surface->readPixels(pm1, 0, 0)) {
        ERRORF(reporter, "readPixels failed");
        return false;
    }

    // Compare and contrast
    float tol = 1.f/256;
    const float tols[4] = {tol, tol, tol, tol};
    auto error = std::function<ComparePixmapsErrorReporter>([&](int x, int y,
                                                                const float diffs[4]) {
        SkASSERT(x >= 0 && y >= 0);
        ERRORF(reporter,
               "Error at %d, %d. Diff in floats: (%f, %f, %f, %f)",
               x, y, diffs[0], diffs[1], diffs[2], diffs[3]);
    });
    ComparePixels(pm0, pm1, tols, error);

    return true;
}

} // anonymous namespace

// This test captures two recordings A and B, plays them back as A then B, and B then A,
// and verifies that the result is the same.
DEF_GRAPHITE_TEST_FOR_RENDERING_CONTEXTS(RecordingOrderTest_Graphite, reporter, context,
                                         CtsEnforcement::kNextRelease) {
    std::unique_ptr<Recorder> recorder = context->makeRecorder();

    (void) run_test(reporter, context, recorder.get());
}
