/*
 * 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/GrGLUtil.h"
#include "gl/GrGLDefines.h"
#include "gl/GrGLInterface.h"
#include "SkApplication.h"
#include "SkCommandLineFlags.h"
#include "SkGpuDevice.h"
#include "SkGraphics.h"

DEFINE_string2(match, m, NULL, "[~][^]substring[$] [...] of test name to run.\n" \
                               "Multiple matches may be separated by spaces.\n" \
                               "~ causes a matching test to always be skipped\n" \
                               "^ requires the start of the test to match\n" \
                               "$ requires the end of the test to match\n" \
                               "^ and $ requires an exact match\n" \
                               "If a test does not match any list entry,\n" \
                               "it is skipped unless some list entry starts with ~");

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

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

SkExampleWindow::SkExampleWindow(void* hwnd)
    : INHERITED(hwnd) {
    fRegistry = SkExample::Registry::Head();
    fCurrExample = fRegistry->factory()(this);

    if (FLAGS_match.count()) {
        for(int i = 0; i < FLAGS_match.count(); ++i) {
            fMatchStrs.push(FLAGS_match[i]);
        }
        // Start with the a matching sample if possible.
        bool found = this->findNextMatch();
        if (!found) {
            SkDebugf("No matching SkExample found.\n");
        }
    }
}

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

        SkSafeUnref(fInterface);
        fInterface = NULL;

        SkSafeUnref(fRenderTarget);
        fRenderTarget = NULL;

        detach();
    }
}

bool SkExampleWindow::setupBackend(DeviceType type) {
    fType = type;

    this->setConfig(SkBitmap::kARGB_8888_Config);
    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);

    setupRenderTarget();

    return true;
}

void SkExampleWindow::setupRenderTarget() {
    GrBackendRenderTargetDesc desc;
    desc.fWidth = SkScalarRound(width());
    desc.fHeight = SkScalarRound(height());
    desc.fConfig = kSkia8888_GrPixelConfig;
    desc.fOrigin = kBottomLeft_GrSurfaceOrigin;
    desc.fSampleCnt = fAttachmentInfo.fSampleCount;
    desc.fStencilBits = fAttachmentInfo.fStencilBits;

    GrGLint buffer;
    GR_GL_GetIntegerv(fInterface, GR_GL_FRAMEBUFFER_BINDING, &buffer);
    desc.fRenderTargetHandle = buffer;

    fRenderTarget = fContext->wrapBackendRenderTarget(desc);

    fContext->setRenderTarget(fRenderTarget);
}

SkCanvas* SkExampleWindow::createCanvas() {
    if (fType == kGPU_DeviceType) {
        if (NULL != fContext && NULL != fRenderTarget) {
            SkAutoTUnref<SkDevice> device(new SkGpuDevice(fContext, fRenderTarget));
            return new SkCanvas(device);
        }
        tearDownBackend();
        setupBackend(kRaster_DeviceType);
    }
    return INHERITED::createCanvas();
}

void SkExampleWindow::draw(SkCanvas* canvas) {
    if (NULL != fCurrExample) {
        fCurrExample->draw(canvas);
    }
    if (fType == kGPU_DeviceType) {

        SkASSERT(NULL != fContext);
        fContext->flush();
    }
    if (fType == kRaster_DeviceType) {
        // need to send the raster bits to the (gpu) window
        fContext->setRenderTarget(fRenderTarget);
        const SkBitmap& bm = getBitmap();
        fRenderTarget->writePixels(0, 0, bm.width(), bm.height(),
                                      kSkia8888_GrPixelConfig,
                                      bm.getPixels(),
                                      bm.rowBytes());
    }
    INHERITED::present();
}

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

#ifdef SK_BUILD_FOR_WIN
void SkExampleWindow::onHandleInval(const SkIRect& rect) {
    RECT winRect;
    winRect.top = rect.top();
    winRect.bottom = rect.bottom();
    winRect.right = rect.right();
    winRect.left = rect.left();
    InvalidateRect((HWND)this->getHWND(), &winRect, false);
}
#endif

bool SkExampleWindow::findNextMatch() {
    bool found = false;
    // Avoid infinite loop by knowing where we started.
    const SkExample::Registry* begin = fRegistry;
    while (!found) {
        fRegistry = fRegistry->next();
        if (NULL == fRegistry) {  // Reached the end of the registered samples. GOTO head.
            fRegistry = SkExample::Registry::Head();
        }
        SkExample* next = fRegistry->factory()(this);
        if (!SkCommandLineFlags::ShouldSkip(fMatchStrs, next->getName().c_str())) {
            fCurrExample = next;
            found = true;
        }
        if (begin == fRegistry) {  // We looped through every sample without finding anything.
            break;
        }
    }
    return found;
}

bool SkExampleWindow::onHandleChar(SkUnichar unichar) {
    if ('n' == unichar) {
        bool found = findNextMatch();
        if (!found) {
            SkDebugf("No SkExample that matches your query\n");
        }
    }
    return true;
}

SkOSWindow* create_sk_window(void* hwnd, int argc, char** argv) {
    SkCommandLineFlags::Parse(argc, argv);
    return new SkExampleWindow(hwnd);
}
