
/*
 * Copyright 2011 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */
#include "SkOSWindow_SDL.h"
#include "SkCanvas.h"
#include "SkColorPriv.h"
#include "SkGLCanvas.h"
#include "SkOSMenu.h"
#include "SkTime.h"

static void post_SkEvent_event() {
    SDL_Event evt;
    evt.type = SDL_USEREVENT;
    evt.user.type = SDL_USEREVENT;
    evt.user.code = 0;
    evt.user.data1 = NULL;
    evt.user.data2 = NULL;
    SDL_PushEvent(&evt);
}

static bool skia_setBitmapFromSurface(SkBitmap* dst, SDL_Surface* src) {
    SkColorType ct;
    SkAlphaType at;

    switch (src->format->BytesPerPixel) {
        case 2:
            ct = kRGB_565_SkColorType;
            at = kOpaque_SkAlphaType;
            break;
        case 4:
            ct = kN32_SkColorType;
            at = kPremul_SkAlphaType;
            break;
        default:
            return false;
    }

    return dst->installPixels(SkImageInfo::Make(src->w, src->h, ct, at), src->pixels, src->pitch);
}

SkOSWindow::SkOSWindow(void* screen) {
    fScreen = reinterpret_cast<SDL_Surface*>(screen);
    this->resize(fScreen->w, fScreen->h);

    uint32_t rmask = SK_R32_MASK << SK_R32_SHIFT;
    uint32_t gmask = SK_G32_MASK << SK_G32_SHIFT;
    uint32_t bmask = SK_B32_MASK << SK_B32_SHIFT;
    uint32_t amask = SK_A32_MASK << SK_A32_SHIFT;

    if (fScreen->flags & SDL_OPENGL) {
        fSurface = NULL;
        fGLCanvas = new SkGLCanvas;
        fGLCanvas->setViewport(fScreen->w, fScreen->h);
    } else {
        fGLCanvas = NULL;
        fSurface = SDL_CreateRGBSurface(SDL_SWSURFACE, fScreen->w, fScreen->h,
                                        32, rmask, gmask, bmask, amask);
    }
}

SkOSWindow::~SkOSWindow() {
    delete fGLCanvas;
    if (fSurface) {
        SDL_FreeSurface(fSurface);
    }
}

#include <OpenGL/gl.h>

void SkOSWindow::doDraw() {
    if (fGLCanvas) {
        glEnable(GL_BLEND);
        glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
        glHint(GL_LINE_SMOOTH_HINT, GL_DONT_CARE);
        glEnable(GL_TEXTURE_2D);
        glClearColor(0, 0, 0, 0);
        glClear(GL_COLOR_BUFFER_BIT);

        int count = fGLCanvas->save();
        this->draw(fGLCanvas);
        fGLCanvas->restoreToCount(count);
        SDL_GL_SwapBuffers( );
    } else {
        if ( SDL_MUSTLOCK(fSurface) ) {
            if ( SDL_LockSurface(fSurface) < 0 ) {
                return;
            }
        }

        SkBitmap bitmap;

        if (skia_setBitmapFromSurface(&bitmap, fSurface)) {
            SkCanvas canvas(bitmap);
            this->draw(&canvas);
        }

        if ( SDL_MUSTLOCK(fSurface) ) {
            SDL_UnlockSurface(fSurface);
        }

        int result = SDL_BlitSurface(fSurface, NULL, fScreen, NULL);
        if (result) {
            SkDebugf("------- SDL_BlitSurface returned %d\n", result);
        }
        SDL_UpdateRect(fScreen, 0, 0, fScreen->w, fScreen->h);
    }
}

static SkKey find_skkey(SDLKey src) {
    // this array must match the enum order in SkKey.h
    static const SDLKey gKeys[] = {
        SDLK_UNKNOWN,
        SDLK_UNKNOWN,   // left softkey
        SDLK_UNKNOWN,   // right softkey
        SDLK_UNKNOWN,   // home
        SDLK_UNKNOWN,   // back
        SDLK_UNKNOWN,   // send
        SDLK_UNKNOWN,   // end
        SDLK_0,
        SDLK_1,
        SDLK_2,
        SDLK_3,
        SDLK_4,
        SDLK_5,
        SDLK_6,
        SDLK_7,
        SDLK_8,
        SDLK_9,
        SDLK_ASTERISK,
        SDLK_HASH,
        SDLK_UP,
        SDLK_DOWN,
        SDLK_LEFT,
        SDLK_RIGHT,
        SDLK_RETURN,    // OK
        SDLK_UNKNOWN,   // volume up
        SDLK_UNKNOWN,   // volume down
        SDLK_UNKNOWN,   // power
        SDLK_UNKNOWN,   // camera
    };

    const SDLKey* array = gKeys;
    for (size_t i = 0; i < SK_ARRAY_COUNT(gKeys); i++) {
        if (array[i] == src) {
            return static_cast<SkKey>(i);
        }
    }
    return kNONE_SkKey;
}

void SkOSWindow::handleSDLEvent(const SDL_Event& event) {
    switch (event.type) {
        case SDL_VIDEORESIZE:
            this->resize(event.resize.w, event.resize.h);
            break;
        case SDL_VIDEOEXPOSE:
            this->doDraw();
            break;
        case SDL_MOUSEMOTION:
            if (event.motion.state == SDL_PRESSED) {
                this->handleClick(event.motion.x, event.motion.y,
                                   SkView::Click::kMoved_State);
            }
            break;
        case SDL_MOUSEBUTTONDOWN:
        case SDL_MOUSEBUTTONUP:
            this->handleClick(event.button.x, event.button.y,
                               event.button.state == SDL_PRESSED ?
                               SkView::Click::kDown_State :
                               SkView::Click::kUp_State);
            break;
        case SDL_KEYDOWN: {
            SkKey sk = find_skkey(event.key.keysym.sym);
            if (kNONE_SkKey != sk) {
                if (event.key.state == SDL_PRESSED) {
                    this->handleKey(sk);
                } else {
                    this->handleKeyUp(sk);
                }
            }
            break;
        }
        case SDL_USEREVENT:
            if (SkEvent::ProcessEvent()) {
                post_SkEvent_event();
            }
            break;
    }
}

void SkOSWindow::onHandleInval(const SkIRect& r) {
    SDL_Event evt;
    evt.type = SDL_VIDEOEXPOSE;
    evt.expose.type = SDL_VIDEOEXPOSE;
    SDL_PushEvent(&evt);
}

void SkOSWindow::onSetTitle(const char title[]) {
    SDL_WM_SetCaption(title, NULL);
}

void SkOSWindow::onAddMenu(const SkOSMenu* sk_menu) {}

///////////////////////////////////////////////////////////////////////////////////////

void SkEvent::SignalNonEmptyQueue() {
    SkDebugf("-------- signal nonempty\n");
    post_SkEvent_event();
}

static Uint32 timer_callback(Uint32 interval) {
//    SkDebugf("-------- timercallback %d\n", interval);
    SkEvent::ServiceQueueTimer();
    return 0;
}

void SkEvent::SignalQueueTimer(SkMSec delay)
{
    SDL_SetTimer(0, NULL);
    if (delay) {
        SDL_SetTimer(delay, timer_callback);
    }
}
