/*
 * 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 "include/core/SkAlphaType.h"
#include "include/core/SkBitmap.h"
#include "include/core/SkCanvas.h"
#include "include/core/SkColor.h"
#include "include/core/SkColorSpace.h"
#include "include/core/SkColorType.h"
#include "include/core/SkImageInfo.h"
#include "include/core/SkPaint.h"
#include "include/core/SkRect.h"
#include "include/core/SkRefCnt.h"
#include "include/core/SkSurface.h"
#include "include/gpu/GpuTypes.h"
#include "include/gpu/ganesh/GrBackendSurface.h"
#include "include/gpu/ganesh/GrDirectContext.h"
#include "include/gpu/ganesh/GrTypes.h"
#include "include/gpu/ganesh/SkSurfaceGanesh.h"
#include "include/private/gpu/ganesh/GrTypesPriv.h"
#include "src/gpu/ganesh/GrDirectContextPriv.h"
#include "src/gpu/ganesh/GrUtil.h"
#include "tests/CtsEnforcement.h"
#include "tests/Test.h"

#include <cstdint>

struct GrContextOptions;

static void check_pixels(skiatest::Reporter* reporter, const SkBitmap& bitmap,
                         GrSurfaceOrigin origin) {
    const uint32_t* canvasPixels = static_cast<const uint32_t*>(bitmap.getPixels());

    bool failureFound = false;
    bool foundNonBlue = false;

    for (int cy = 0; cy < 8 && !failureFound; ++cy) {
        int cx = 4; // Just need to check one column;
        SkPMColor canvasPixel = canvasPixels[cy * 8 + cx];
        // We don't know which way the GPU will snap so the non-blue line could either be at row
        // 3 or 4 since we drew the line at a y value of 4. We check that one of those two values
        // is green and all the rest are blue. The key thing is that we should not get any red
        // values since the green line in the saveLayer should snap the same way and overwrite the
        // red line.
        if (cy == 3) {
            if (canvasPixel != 0xFFFF0000 && canvasPixel != 0xFF00FF00) {
                failureFound = true;
                ERRORF(reporter, "Wrong color at %d, %d. Got 0x%08x when we expected Blue or Green."
                       " Origin is: %s",
                       cx, cy, canvasPixel, GrSurfaceOriginToStr(origin));
            }
            if (canvasPixel != 0XFFFF0000) {
                foundNonBlue = true;
            }
        } else {
            SkPMColor expectedPixel;
            if (cy == 4 && !foundNonBlue) {
                expectedPixel = 0xFF00FF00; // Green
            } else {
                expectedPixel = 0xFFFF0000; // Blue
            }
            if (canvasPixel != expectedPixel) {
                failureFound = true;
                ERRORF(reporter,
                       "Wrong color at %d, %d. Got 0x%08x when we expected 0x%08x. Origin is: %s",
                       cx, cy, canvasPixel, expectedPixel, GrSurfaceOriginToStr(origin));
            }
        }
    }
}

static void run_test(skiatest::Reporter* reporter,
                     GrDirectContext* context,
                     GrSurfaceOrigin origin) {
    using namespace skgpu;

    Protected isProtected = Protected(context->priv().caps()->supportsProtectedContent());

    auto beTexture = context->createBackendTexture(8,
                                                   8,
                                                   kRGBA_8888_SkColorType,
                                                   Mipmapped::kNo,
                                                   GrRenderable::kYes,
                                                   isProtected);
    REPORTER_ASSERT(reporter, beTexture.isValid());
    if (!beTexture.isValid()) {
        return;
    }

    auto surface = SkSurfaces::WrapBackendTexture(
            context, beTexture, origin, 0, kRGBA_8888_SkColorType, nullptr, nullptr);
    REPORTER_ASSERT(reporter, surface);
    if (!surface) {
        return;
    }

    SkCanvas* canvas = surface->getCanvas();

    canvas->clear(SK_ColorBLUE);

    SkPaint paint;
    paint.setColor(SK_ColorRED);
    canvas->drawLine({ 0,4 }, { 8,4 }, paint);

    SkRect bounds = SkRect::MakeWH(8, 8);
    SkPaint layerPaint;
    canvas->saveLayer(bounds, &paint);
    paint.setColor(SK_ColorGREEN);
    canvas->drawLine({ 0,4 }, { 8,4 }, paint);
    canvas->restore();

    SkBitmap bitmap;
    bitmap.allocPixels(SkImageInfo::Make(8, 8, kRGBA_8888_SkColorType, kPremul_SkAlphaType));
    surface->readPixels(bitmap, 0, 0);

    check_pixels(reporter, bitmap, origin);

    context->deleteBackendTexture(beTexture);
}

DEF_GANESH_TEST_FOR_RENDERING_CONTEXTS(SaveLayerOrigin,
                                       reporter,
                                       context_info,
                                       CtsEnforcement::kApiLevel_T) {
    GrDirectContext* context = context_info.directContext();
    run_test(reporter, context, kBottomLeft_GrSurfaceOrigin);
    run_test(reporter, context, kTopLeft_GrSurfaceOrigin);
}
