
/*
 * Copyright 2013 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "ppapi/cpp/completion_callback.h"
#include "ppapi/cpp/graphics_2d.h"
#include "ppapi/cpp/image_data.h"
#include "ppapi/cpp/instance.h"
#include "ppapi/cpp/module.h"
#include "ppapi/cpp/point.h"
#include "ppapi/cpp/rect.h"
#include "ppapi/cpp/var.h"

#include "SkBase64.h"
#include "SkBitmap.h"
#include "SkCanvas.h"
#include "SkColor.h"
#include "SkDebugger.h"
#include "SkGraphics.h"
#include "SkStream.h"
#include "SkString.h"

class SkiaInstance;

// Used by SkDebugf
SkiaInstance* gPluginInstance;

void FlushCallback(void* data, int32_t result);

// Skia's subclass of pp::Instance, our interface with the browser.
class SkiaInstance : public pp::Instance {
public:
    explicit SkiaInstance(PP_Instance instance)
        : pp::Instance(instance)
        , fCanvas(NULL)
        , fFlushLoopRunning(false)
        , fFlushPending(false)

    {
        gPluginInstance = this;
        SkGraphics::Init();
    }

    virtual ~SkiaInstance() {
        SkGraphics::Term();
        gPluginInstance = NULL;
    }

    virtual void HandleMessage(const pp::Var& var_message) {
        // Receive a message from javascript.
        if (var_message.is_string()) {
            SkString msg(var_message.AsString().c_str());
            if (msg.startsWith("init")) {
            } else if (msg.startsWith("LoadSKP")) {
                size_t startIndex = strlen("LoadSKP");
                size_t dataSize = msg.size()/sizeof(char) - startIndex;
                SkBase64 decodedData;
                decodedData.decode(msg.c_str() + startIndex, dataSize);
                size_t decodedSize = 3 * (dataSize / 4);
                SkDebugf("Got size: %d\n", decodedSize);
                if (!decodedData.getData()) {
                    SkDebugf("Failed to decode SKP\n");
                    return;
                }
                SkMemoryStream pictureStream(decodedData.getData(), decodedSize);
                SkPicture* picture = SkPicture::CreateFromStream(&pictureStream);
                if (NULL == picture) {
                    SkDebugf("Failed to create SKP.\n");
                    return;
                }
                fDebugger.loadPicture(picture);
                picture->unref();

                // Set up the command list.
                SkTArray<SkString>* commands = fDebugger.getDrawCommandsAsStrings();
                PostMessage("ClearCommands");
                for (int i = 0; i < commands->count(); ++i) {
                    SkString addCommand("AddCommand:");
                    addCommand.append((*commands)[i]);
                    PostMessage(addCommand.c_str());
                }
                PostMessage("UpdateCommands");

                // Set the overview text.
                SkString overviewText;
                fDebugger.getOverviewText(NULL, 0.0, &overviewText, 1);
                overviewText.prepend("SetOverview:");
                PostMessage(overviewText.c_str());

                // Draw the SKP.
                if (!fFlushLoopRunning) {
                    Paint();
                }
            } else if (msg.startsWith("CommandSelected:")) {
                size_t startIndex = strlen("CommandSelected:");
                int index = atoi(msg.c_str() + startIndex);
                fDebugger.setIndex(index);
                if (!fFlushLoopRunning) {
                    Paint();
                }
            } else if (msg.startsWith("Rewind")) {
                fCanvas->clear(SK_ColorWHITE);
                fDebugger.setIndex(0);
                if (!fFlushLoopRunning) {
                    Paint();
                }
            } else if (msg.startsWith("StepBack")) {
                fCanvas->clear(SK_ColorWHITE);
                int currentIndex = fDebugger.index();
                if (currentIndex > 1) {
                    fDebugger.setIndex(currentIndex - 1);
                    if (!fFlushLoopRunning) {
                        Paint();
                    }
                }
            } else if (msg.startsWith("Pause")) {
                // TODO(borenet)
            } else if (msg.startsWith("StepForward")) {
                int currentIndex = fDebugger.index();
                if (currentIndex < fDebugger.getSize() -1) {
                    fDebugger.setIndex(currentIndex + 1);
                    if (!fFlushLoopRunning) {
                        Paint();
                    }
                }
            } else if (msg.startsWith("Play")) {
                fDebugger.setIndex(fDebugger.getSize() - 1);
                if (!fFlushLoopRunning) {
                    Paint();
                }
            }
        }
    }

    void Paint() {
        if (!fImage.is_null()) {
            fDebugger.draw(fCanvas);
            fDeviceContext.PaintImageData(fImage, pp::Point(0, 0));
            if (!fFlushPending) {
                fFlushPending = true;
                fDeviceContext.Flush(pp::CompletionCallback(&FlushCallback, this));
            } else {
                SkDebugf("A flush is pending... Skipping flush.\n");
            }
        } else {
            SkDebugf("No pixels to write to!\n");
        }
    }

    virtual void DidChangeView(const pp::Rect& position, const pp::Rect& clip) {
        if (position.size().width() == fWidth &&
            position.size().height() == fHeight) {
            return;  // We don't care about the position, only the size.
        }
        fWidth = position.size().width();
        fHeight = position.size().height();

        fDeviceContext = pp::Graphics2D(this, pp::Size(fWidth, fHeight), false);
        if (!BindGraphics(fDeviceContext)) {
            SkDebugf("Couldn't bind the device context\n");
            return;
        }
        fImage = pp::ImageData(this,
                               PP_IMAGEDATAFORMAT_BGRA_PREMUL,
                               pp::Size(fWidth, fHeight), false);
        fBitmap.setConfig(SkBitmap::kARGB_8888_Config, fWidth, fHeight);
        fBitmap.setPixels(fImage.data());
        if (fCanvas) {
            delete fCanvas;
        }
        fCanvas = new SkCanvas(fBitmap);
        fCanvas->clear(SK_ColorWHITE);
        if (!fFlushLoopRunning) {
            Paint();
        }
    }

    void OnFlush() {
        fFlushLoopRunning = true;
        fFlushPending = false;
        Paint();
    }

private:
    pp::Graphics2D fDeviceContext;
    pp::ImageData fImage;
    int fWidth;
    int fHeight;

    SkBitmap fBitmap;
    SkCanvas* fCanvas;
    SkDebugger fDebugger;

    bool fFlushLoopRunning;
    bool fFlushPending;
};

void FlushCallback(void* data, int32_t result) {
    static_cast<SkiaInstance*>(data)->OnFlush();
}

class SkiaModule : public pp::Module {
public:
    SkiaModule() : pp::Module() {}
    virtual ~SkiaModule() {}

    virtual pp::Instance* CreateInstance(PP_Instance instance) {
        return new SkiaInstance(instance);
    }
};

namespace pp {
Module* CreateModule() {
    return new SkiaModule();
}
}  // namespace pp
