/*
 * 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 "SkExample.h"

#include "gl/GrGLInterface.h"
#include "SkApplication.h"
#include "SkCanvas.h"
#include "SkGradientShader.h"
#include "SkGraphics.h"
#include "SkGr.h"

void application_init() {
    SkGraphics::Init();
    SkEvent::Init();
}

void application_term() {
    SkEvent::Term();
    SkGraphics::Term();
}

SkExampleWindow::SkExampleWindow(void* hwnd)
    : INHERITED(hwnd) {
    fType = SkExampleWindow::kGPU_DeviceType;
    fRenderTarget = NULL;
    fRotationAngle = 0;
    this->setTitle();
    this->setUpBackend();
}

SkExampleWindow::~SkExampleWindow() {
    tearDownBackend();
}

void SkExampleWindow::tearDownBackend() {
    SkSafeUnref(fContext);
    fContext = NULL;

    SkSafeUnref(fInterface);
    fInterface = NULL;

    SkSafeUnref(fRenderTarget);
    fRenderTarget = NULL;

    INHERITED::detach();
}

void SkExampleWindow::setTitle() {
    SkString title("SkiaExample ");
    title.appendf(fType == kRaster_DeviceType ? "raster" : "opengl");
    INHERITED::setTitle(title.c_str());
}

bool SkExampleWindow::setUpBackend() {
    this->setColorType(kRGBA_8888_SkColorType);
    this->setVisibleP(true);
    this->setClipToBounds(false);

    bool result = attach(kNativeGL_BackEndType, 0 /*msaa*/, &fAttachmentInfo);
    if (false == result) {
        SkDebugf("Not possible to create backend.\n");
        detach();
        return false;
    }

    fInterface = GrGLCreateNativeInterface();

    SkASSERT(NULL != fInterface);

    fContext = GrContext::Create(kOpenGL_GrBackend, (GrBackendContext)fInterface);
    SkASSERT(NULL != fContext);

    this->setUpRenderTarget();
    return true;
}

void SkExampleWindow::setUpRenderTarget() {
    SkSafeUnref(fRenderTarget);
    fRenderTarget = this->renderTarget(fAttachmentInfo, fInterface, fContext);
}

void SkExampleWindow::drawContents(SkCanvas* canvas) {
    // Clear background
    canvas->drawColor(SK_ColorWHITE);

    SkPaint paint;
    paint.setColor(SK_ColorRED);

    // Draw a rectangle with red paint
    SkRect rect = {
            10, 10,
            128, 128
    };
    canvas->drawRect(rect, paint);

    // Set up a linear gradient and draw a circle
    {
        SkPoint linearPoints[] = {
                {0, 0},
                {300, 300}
        };
        SkColor linearColors[] = {SK_ColorGREEN, SK_ColorBLACK};

        SkShader* shader = SkGradientShader::CreateLinear(
                linearPoints, linearColors, NULL, 2,
                SkShader::kMirror_TileMode);
        SkAutoUnref shader_deleter(shader);

        paint.setShader(shader);
        paint.setFlags(SkPaint::kAntiAlias_Flag);

        canvas->drawCircle(200, 200, 64, paint);

        // Detach shader
        paint.setShader(NULL);
    }

    // Draw a message with a nice black paint.
    paint.setFlags(
            SkPaint::kAntiAlias_Flag |
            SkPaint::kSubpixelText_Flag |  // ... avoid waggly text when rotating.
            SkPaint::kUnderlineText_Flag);
    paint.setColor(SK_ColorBLACK);
    paint.setTextSize(20);

    canvas->save();

    static const char message[] = "Hello Skia!!!";

    // Translate and rotate
    canvas->translate(300, 300);
    fRotationAngle += 0.2f;
    if (fRotationAngle > 360) {
        fRotationAngle -= 360;
    }
    canvas->rotate(fRotationAngle);

    // Draw the text:
    canvas->drawText(message, strlen(message), 0, 0, paint);

    canvas->restore();
}

void SkExampleWindow::draw(SkCanvas* canvas) {
    drawContents(canvas);
    // in case we have queued drawing calls
    fContext->flush();
    // Invalidate the window to force a redraw. Poor man's animation mechanism.
    this->inval(NULL);

    if (kRaster_DeviceType == fType) {
        // need to send the raster bits to the (gpu) window
        SkImage* snap = fSurface->newImageSnapshot();
        size_t rowBytes;
        SkImageInfo info;
        const void* pixels = snap->peekPixels(&info, &rowBytes);
        fRenderTarget->writePixels(0, 0, snap->width(), snap->height(),
                                        SkImageInfo2GrPixelConfig(info.colorType(),
                                                                info.alphaType(),
                                                                info.profileType()),
                                        pixels,
                                        rowBytes,
                                        GrContext::kFlushWrites_PixelOp);
        SkSafeUnref(snap);
    }
    INHERITED::present();
}

void SkExampleWindow::onSizeChange() {
    setUpRenderTarget();
}

bool SkExampleWindow::onHandleChar(SkUnichar unichar) {
    if (' ' == unichar) {
        fType = fType == kRaster_DeviceType ? kGPU_DeviceType: kRaster_DeviceType;
        tearDownBackend();
        setUpBackend();
        this->setTitle();
        this->inval(NULL);
    }
    return true;
}

SkOSWindow* create_sk_window(void* hwnd, int , char** ) {
    return new SkExampleWindow(hwnd);
}
