/*
 * 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 <cstdio>
#include <cstdlib>
#include <sstream>
#include <string>

#include "src/core/SkAutoPixmapStorage.h"
#include "src/core/SkMipmap.h"
#include "src/core/SkUtils.h"
#include "tools/flags/CommandLineFlags.h"

#include "tools/fiddle/fiddle_main.h"

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.");

#include "include/gpu/GrBackendSurface.h"
#include "src/gpu/GrContextPriv.h"
#include "src/gpu/GrGpu.h"
#include "src/gpu/GrRenderTarget.h"
#include "tools/gpu/gl/GLTestContext.h"

// Globals externed in fiddle_main.h
sk_sp<GrTexture>      backingTexture;  // not externed
GrBackendTexture      backEndTexture;

sk_sp<GrRenderTarget> backingRenderTarget; // not externed
GrBackendRenderTarget backEndRenderTarget;

sk_sp<GrTexture>      backingTextureRenderTarget;  // not externed
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.

// 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;

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(const sk_sp<SkSurface>& surface) {
    sk_sp<SkImage> img(surface->makeImageSnapshot());
    return img ? img->encodeToData() : nullptr;
}

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

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

    auto resourceProvider = context->priv().resourceProvider();

    // This config must match the SkColorType used in draw.cpp in the SkImage and Surface factories
    auto format = resourceProvider->caps()->getDefaultBackendFormat(
            SkColorTypeToGrColorType(kRGBA_8888_SkColorType), GrRenderable::kNo);
    auto renderableFormat = resourceProvider->caps()->getDefaultBackendFormat(
            SkColorTypeToGrColorType(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;
        if (kN32_SkColorType != kRGBA_8888_SkColorType) {
            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;
        }
        int mipLevelCount = GrMipmapped::kYes == options.fMipMapping
                                    ? SkMipmap::ComputeLevelCount(bm.width(), bm.height())
                                    : 1;
        std::unique_ptr<GrMipLevel[]> texels(new GrMipLevel[mipLevelCount]);

        texels[0].fPixels = pixmap->addr();
        texels[0].fRowBytes = pixmap->rowBytes();

        for (int i = 1; i < mipLevelCount; i++) {
            texels[i].fPixels = nullptr;
            texels[i].fRowBytes = 0;
        }

        backingTexture = resourceProvider->createTexture(
                bm.dimensions(), format, GrColorType::kRGBA_8888, GrRenderable::kNo, 1,
                SkBudgeted::kNo, GrProtected::kNo, texels.get(), mipLevelCount);
        if (!backingTexture) {
            fputs("Failed to create backingTexture.\n", stderr);
            return false;
        }

        backEndTexture = backingTexture->getBackendTexture();
        if (!backEndTexture.isValid()) {
            fputs("BackingTexture is invalid.\n", stderr);
            return false;
        }
    }

    SkISize offscreenDims = {options.fOffScreenWidth, options.fOffScreenHeight};
    SkAutoTMalloc<uint32_t> data(offscreenDims.area());
    sk_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) };

        sk_sp<GrTexture> tmp = resourceProvider->createTexture(
                offscreenDims, renderableFormat, GrColorType::kRGBA_8888, GrRenderable::kYes,
                options.fOffScreenSampleCount, SkBudgeted::kNo, GrProtected::kNo, &level0, 1);
        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;
        }
    }

    {
        int mipLevelCount =
                GrMipmapped::kYes == options.fOffScreenMipMapping
                        ? SkMipmap::ComputeLevelCount(offscreenDims.width(), offscreenDims.height())
                        : 1;
        std::unique_ptr<GrMipLevel[]> texels(new GrMipLevel[mipLevelCount]);

        texels[0].fPixels = data.get();
        texels[0].fRowBytes = offscreenDims.width()*sizeof(uint32_t);

        for (int i = 1; i < mipLevelCount; i++) {
            texels[i].fPixels = nullptr;
            texels[i].fRowBytes = 0;
        }

        backingTextureRenderTarget = resourceProvider->createTexture(
                offscreenDims, renderableFormat, GrColorType::kRGBA_8888, GrRenderable::kYes,
                options.fOffScreenSampleCount, SkBudgeted::kNo, GrProtected::kNo, texels.get(),
                mipLevelCount);
        if (!backingTextureRenderTarget || !backingTextureRenderTarget->asRenderTarget()) {
            fputs("backingTextureRenderTarget is invalid.\n", stderr);
            return false;
        }

        backEndTextureRenderTarget = backingTextureRenderTarget->getBackendTexture();
        if (!backEndTextureRenderTarget.isValid()) {
            fputs("backEndTextureRenderTarget is invalid.\n", stderr);
            return false;
        }
    }


    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 (options.source) {
        sk_sp<SkData> data(SkData::MakeFromFileName(options.source));
        if (!data) {
            perror(options.source);
            return 1;
        } else {
            image = SkImage::MakeFromEncoded(std::move(data));
            if (!image) {
                perror("Unable to decode the source image.");
                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 = SkSurface::MakeRaster(info);
        srand(0);
        draw(prepare_canvas(rasterSurface->getCanvas()));
        rasterData = encode_snapshot(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 = SkSurface::MakeRenderTarget(direct.get(), SkBudgeted::kNo, info);
            if (!surface) {
                fputs("Unable to get render surface.\n", stderr);
                exit(1);
            }
            srand(0);
            draw(prepare_canvas(surface->getCanvas()));
            gpuData = encode_snapshot(surface);
        }
    }
#endif
    if (options.pdf) {
        SkDynamicMemoryWStream pdfStream;
        auto document = SkPDF::MakeDocument(&pdfStream);
        if (document) {
            srand(0);
            draw(prepare_canvas(document->beginPage(options.size.width(), options.size.height())));
            document->close();
            pdfData = pdfStream.detachAsData();
        }
    }
    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;
}
