/*
 * 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_grcontext().
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;
}

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

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);
    }
    if (options.gpu) {
        std::unique_ptr<sk_gpu_test::GLTestContext> glContext;
        sk_sp<GrContext> grContext = create_grcontext(gGLDriverInfo, &glContext);
        if (!grContext) {
            fputs("Unable to get GrContext.\n", stderr);
        } else {
            if (!setup_backend_objects(grContext.get(), source, options)) {
                fputs("Unable to create backend objects.\n", stderr);
                exit(1);
            }

            auto surface = SkSurface::MakeRenderTarget(grContext.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);
        }
    }
    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;
}
