/*
 * 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 "include/codec/SkCodec.h"
#include "include/codec/SkJpegDecoder.h"
#include "include/core/SkBitmap.h"
#include "include/core/SkPicture.h"
#include "include/encode/SkPngEncoder.h"
#include "include/gpu/ganesh/GrBackendSurface.h"
#include "include/gpu/ganesh/SkSurfaceGanesh.h"
#include "src/core/SkAutoPixmapStorage.h"
#include "src/core/SkMemset.h"
#include "src/core/SkMipmap.h"
#include "src/gpu/ganesh/GrDirectContextPriv.h"
#include "src/gpu/ganesh/GrGpu.h"
#include "src/gpu/ganesh/GrRenderTarget.h"
#include "src/gpu/ganesh/GrResourceProvider.h"
#include "src/gpu/ganesh/GrTexture.h"

#include "tools/flags/CommandLineFlags.h"
#include "tools/ganesh/gl/GLTestContext.h"
#include "tools/gpu/ManagedBackendTexture.h"

#if defined(SK_CODEC_DECODES_PNG_WITH_LIBPNG)
#include "include/codec/SkPngDecoder.h"
#endif

#if defined(SK_SUPPORT_PDF)
#if !defined(SK_CODEC_DECODES_JPEG) || !defined(SK_CODEC_ENCODES_JPEG)
#error "Need jpeg for PDF backend"
#endif
#include "include/docs/SkPDFDocument.h"
#include "include/docs/SkPDFJpegHelpers.h"
#endif

#if defined(SK_FONTMGR_FONTCONFIG_AVAILABLE)
#include "include/ports/SkFontMgr_fontconfig.h"
#include "include/ports/SkFontScanner_FreeType.h"
#endif

#include <cstdio>
#include <cstdlib>
#include <sstream>
#include <string>

// fiddle_main.h (purposefully) pollutes the global namespace with very generic identifiers like
// "image", "duration", "frame", and "fontMgr". As such it is something of an
// "implementation header" and should be included last to avoid name shadowing warnings.
#include "tools/fiddle/fiddle_main.h"

using namespace skia_private;

static DEFINE_double(duration, 1.0,
                     "The total duration, in seconds, of the animation we are drawing.");
static DEFINE_double(frame, 1.0,
                     "A double value in [0, 1] that specifies the point in animation to draw.");

// Globals externed in fiddle_main.h
GrBackendTexture backEndTexture;
GrBackendRenderTarget backEndRenderTarget;
GrBackendTexture backEndTextureRenderTarget;
SkBitmap source;
sk_sp<SkImage> image;
double duration; // The total duration of the animation in seconds.
double frame;    // A value in [0, 1] of where we are in the animation.
sk_sp<SkFontMgr> fontMgr;

// Global used by the local impl of SkDebugf.
std::ostringstream gTextOutput;

// Global to record the GL driver info via create_direct_context().
std::ostringstream gGLDriverInfo;

sk_sp<sk_gpu_test::ManagedBackendTexture> managedBackendTextureRenderTarget;
sk_sp<sk_gpu_test::ManagedBackendTexture> managedBackendTexture;
sk_sp<GrRenderTarget> backingRenderTarget;

void SkDebugf(const char * fmt, ...) {
    va_list args;
    va_start(args, fmt);
    char formatbuffer[1024];
    int n = vsnprintf(formatbuffer, sizeof(formatbuffer), fmt, args);
    va_end(args);
    if (n>=0 && n<=int(sizeof(formatbuffer))) {
        gTextOutput.write(formatbuffer, n);
    }
}

static void encode_to_base64(const void* data, size_t size, FILE* out) {
    const uint8_t* input = reinterpret_cast<const uint8_t*>(data);
    const uint8_t* end = &input[size];
    static const char codes[] =
            "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
            "abcdefghijklmnopqrstuvwxyz0123456789+/";
    while (input != end) {
        uint8_t b = (*input & 0xFC) >> 2;
        fputc(codes[b], out);
        b = (*input & 0x03) << 4;
        ++input;
        if (input == end) {
            fputc(codes[b], out);
            fputs("==", out);
            return;
        }
        b |= (*input & 0xF0) >> 4;
        fputc(codes[b], out);
        b = (*input & 0x0F) << 2;
        ++input;
        if (input == end) {
            fputc(codes[b], out);
            fputc('=', out);
            return;
        }
        b |= (*input & 0xC0) >> 6;
        fputc(codes[b], out);
        b = *input & 0x3F;
        fputc(codes[b], out);
        ++input;
    }
}


static void dump_output(const void* data, size_t size,
                        const char* name, bool last = true) {
    printf("\t\"%s\": \"", name);
    encode_to_base64(data, size, stdout);
    fputs(last ? "\"\n" : "\",\n", stdout);
}

static void dump_output(const sk_sp<SkData>& data,
                        const char* name, bool last = true) {
    if (data) {
        dump_output(data->data(), data->size(), name, last);
    }
}

static sk_sp<SkData> encode_snapshot(GrDirectContext* ctx, const sk_sp<SkSurface>& surface) {
    sk_sp<SkImage> img(surface->makeImageSnapshot());
    return SkPngEncoder::Encode(ctx, img.get(), {});
}

static SkCanvas* prepare_canvas(SkCanvas * canvas) {
    canvas->clear(SK_ColorWHITE);
    return canvas;
}

#ifdef SK_GL
static bool setup_backend_objects(GrDirectContext* dContext,
                                  const SkBitmap& bm,
                                  const DrawOptions& options) {
    if (!dContext) {
        fputs("Context is null.\n", stderr);
        return false;
    }

    // This config must match the SkColorType used in draw.cpp in the SkImage and Surface factories
    GrBackendFormat renderableFormat = dContext->defaultBackendFormat(kRGBA_8888_SkColorType,
                                                                      GrRenderable::kYes);

    if (!bm.empty()) {
        SkPixmap originalPixmap;
        SkPixmap* pixmap = &originalPixmap;
        if (!bm.peekPixels(&originalPixmap)) {
            fputs("Unable to peekPixels.\n", stderr);
            return false;
        }

        SkAutoPixmapStorage rgbaPixmap;
        constexpr bool kRGBAIsNative = kN32_SkColorType == kRGBA_8888_SkColorType;
        if ((!kRGBAIsNative)) {
            if (!rgbaPixmap.tryAlloc(bm.info().makeColorType(kRGBA_8888_SkColorType))) {
                fputs("Unable to alloc rgbaPixmap.\n", stderr);
                return false;
            }
            if (!bm.readPixels(rgbaPixmap)) {
                fputs("Unable to read rgbaPixmap.\n", stderr);
                return false;
            }
            pixmap = &rgbaPixmap;
        }

        managedBackendTexture = sk_gpu_test::ManagedBackendTexture::MakeFromPixmap(
                dContext,
                *pixmap,
                options.fMipMapping,
                GrRenderable::kNo,
                GrProtected::kNo);
        if (!managedBackendTexture) {
            fputs("Failed to create backEndTexture.\n", stderr);
            return false;
        }
        backEndTexture = managedBackendTexture->texture();
    }

    {
        auto resourceProvider = dContext->priv().resourceProvider();

        SkISize offscreenDims = {options.fOffScreenWidth, options.fOffScreenHeight};
        AutoTMalloc<uint32_t> data(offscreenDims.area());
        SkOpts::memset32(data.get(), 0, offscreenDims.area());

        // This backend object should be renderable but not textureable. Given the limitations
        // of how we're creating it though it will wind up being secretly textureable.
        // We use this fact to initialize it with data but don't allow mipmaps
        GrMipLevel level0 = {data.get(), offscreenDims.width()*sizeof(uint32_t), nullptr};

        constexpr int kSampleCnt = 1;
        sk_sp<GrTexture> tmp =
                resourceProvider->createTexture(offscreenDims,
                                                renderableFormat,
                                                GrTextureType::k2D,
                                                GrColorType::kRGBA_8888,
                                                GrRenderable::kYes,
                                                kSampleCnt,
                                                skgpu::Budgeted::kNo,
                                                skgpu::Mipmapped::kNo,
                                                GrProtected::kNo,
                                                &level0,
                                                /*label=*/"Fiddle_SetupBackendObjects");
        if (!tmp || !tmp->asRenderTarget()) {
            fputs("GrTexture is invalid.\n", stderr);
            return false;
        }

        backingRenderTarget = sk_ref_sp(tmp->asRenderTarget());

        backEndRenderTarget = backingRenderTarget->getBackendRenderTarget();
        if (!backEndRenderTarget.isValid()) {
            fputs("BackEndRenderTarget is invalid.\n", stderr);
            return false;
        }
    }

    {
        managedBackendTextureRenderTarget = sk_gpu_test::ManagedBackendTexture::MakeWithData(
            dContext,
            options.fOffScreenWidth,
            options.fOffScreenHeight,
            renderableFormat,
            SkColors::kTransparent,
            options.fOffScreenMipMapping,
            GrRenderable::kYes,
            GrProtected::kNo);
        if (!managedBackendTextureRenderTarget) {
            fputs("Failed to create backendTextureRenderTarget.\n", stderr);
            return false;
        }
        backEndTextureRenderTarget = managedBackendTextureRenderTarget->texture();
    }

    return true;
}
#endif

int main(int argc, char** argv) {
    CommandLineFlags::Parse(argc, argv);
    duration = FLAGS_duration;
    frame = FLAGS_frame;
    DrawOptions options = GetDrawOptions();
    // If textOnly then only do one type of image, otherwise the text
    // output is duplicated for each type.
    if (options.textOnly) {
        options.raster = true;
        options.gpu = false;
        options.pdf = false;
        options.skp = false;
    }
#if defined(SK_FONTMGR_FONTCONFIG_AVAILABLE)
    fontMgr = SkFontMgr_New_FontConfig(nullptr, SkFontScanner_Make_FreeType());
#else
    fontMgr = SkFontMgr::RefEmpty();
#endif
    if (options.source) {
        sk_sp<SkData> data(SkData::MakeFromFileName(options.source));
        if (!data) {
            perror(options.source);
            return 1;
        }
        std::unique_ptr<SkCodec> codec = nullptr;
#if defined(SK_CODEC_DECODES_PNG_WITH_LIBPNG)
        if (SkPngDecoder::IsPng(data->data(), data->size())) {
            codec = SkPngDecoder::Decode(data, nullptr);
        } else
#endif
        if (SkJpegDecoder::IsJpeg(data->data(), data->size())) {
            codec = SkJpegDecoder::Decode(data, nullptr);
        } else {
            perror("Unsupported file format\n");
            return 1;
        }
        if (!codec) {
            perror("Corrupt source image file\n");
            return 1;
        }
        image = std::get<0>(codec->getImage());
        if (!image) {
            perror("Unable to decode the source image.\n");
            return 1;
        }
        SkAssertResult(image->asLegacyBitmap(&source));
    }
    sk_sp<SkData> rasterData, gpuData, pdfData, skpData;
    SkColorType colorType = kN32_SkColorType;
    sk_sp<SkColorSpace> colorSpace = nullptr;
    if (options.f16) {
        SkASSERT(options.srgb);
        colorType = kRGBA_F16_SkColorType;
        colorSpace = SkColorSpace::MakeSRGBLinear();
    } else if (options.srgb) {
        colorSpace = SkColorSpace::MakeSRGB();
    }
    SkImageInfo info = SkImageInfo::Make(options.size.width(), options.size.height(), colorType,
                                         kPremul_SkAlphaType, colorSpace);
    if (options.raster) {
        auto rasterSurface = SkSurfaces::Raster(info);
        srand(0);
        draw(prepare_canvas(rasterSurface->getCanvas()));
        rasterData = encode_snapshot(nullptr, rasterSurface);
    }
#ifdef SK_GL
    if (options.gpu) {
        std::unique_ptr<sk_gpu_test::GLTestContext> glContext;
        sk_sp<GrDirectContext> direct = create_direct_context(gGLDriverInfo, &glContext);
        if (!direct) {
            fputs("Unable to get GrContext.\n", stderr);
        } else {
            if (!setup_backend_objects(direct.get(), source, options)) {
                fputs("Unable to create backend objects.\n", stderr);
                exit(1);
            }

            auto surface = SkSurfaces::RenderTarget(direct.get(), skgpu::Budgeted::kNo, info);
            if (!surface) {
                fputs("Unable to get render surface.\n", stderr);
                exit(1);
            }
            srand(0);
            draw(prepare_canvas(surface->getCanvas()));
            gpuData = encode_snapshot(direct.get(), surface);
        }
    }
#endif

#if defined(SK_SUPPORT_PDF)
    if (options.pdf) {
        SkDynamicMemoryWStream pdfStream;
        auto document = SkPDF::MakeDocument(&pdfStream, SkPDF::JPEG::MetadataWithCallbacks());
        if (document) {
            srand(0);
            draw(prepare_canvas(document->beginPage(options.size.width(), options.size.height())));
            document->close();
            pdfData = pdfStream.detachAsData();
        }
    }
#endif

    if (options.skp) {
        auto size = SkSize::Make(options.size);
        SkPictureRecorder recorder;
        srand(0);
        draw(prepare_canvas(recorder.beginRecording(size.width(), size.height())));
        auto picture = recorder.finishRecordingAsPicture();
        SkDynamicMemoryWStream skpStream;
        picture->serialize(&skpStream);
        skpData = skpStream.detachAsData();
    }

    printf("{\n");
    if (!options.textOnly) {
        dump_output(rasterData, "Raster", false);
        dump_output(gpuData, "Gpu", false);
        dump_output(pdfData, "Pdf", false);
        dump_output(skpData, "Skp", false);
    } else {
        std::string textoutput = gTextOutput.str();
        dump_output(textoutput.c_str(), textoutput.length(), "Text", false);
    }
    std::string glinfo = gGLDriverInfo.str();
    dump_output(glinfo.c_str(), glinfo.length(), "GLInfo", true);
    printf("}\n");

    return 0;
}
