/*
    SDL - Simple DirectMedia Layer
    Copyright (C) 1997-2010 Sam Lantinga

    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Lesser General Public
    License as published by the Free Software Foundation; either
    version 2.1 of the License, or (at your option) any later version.

    This library is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    Lesser General Public License for more details.

    You should have received a copy of the GNU Lesser General Public
    License along with this library; if not, write to the Free Software
    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA

    Sam Lantinga
    slouken@libsdl.org
*/
#include "SDL_config.h"

#include "SDL_syswm.h"
#include "../SDL_sysvideo.h"
#include "../../events/SDL_keyboard_c.h"

#include "SDL_DirectFB_video.h"


int
DirectFB_CreateWindow(_THIS, SDL_Window * window)
{
    SDL_DFB_DEVICEDATA(_this);
    SDL_DFB_DISPLAYDATA(_this, window);
    DFB_WindowData *windata = NULL;
    DFBWindowOptions wopts;
    DFBWindowDescription desc;
    IDirectFBFont *font;
    int ret, x, y;

    SDL_DFB_CALLOC(window->driverdata, 1, sizeof(DFB_WindowData));
    windata = (DFB_WindowData *) window->driverdata;

    windata->is_managed = devdata->has_own_wm;

    SDL_DFB_CHECKERR(devdata->dfb->SetCooperativeLevel(devdata->dfb,
                                                       DFSCL_NORMAL));
    SDL_DFB_CHECKERR(dispdata->layer->SetCooperativeLevel(dispdata->layer,
                                                          DLSCL_ADMINISTRATIVE));

    /* Fill the window description. */
    if (window->x == SDL_WINDOWPOS_CENTERED) {
        x = (dispdata->cw - window->w) / 2;
    } else if (window->x == SDL_WINDOWPOS_UNDEFINED) {
        x = 0;
    } else {
        x = window->x;
    }
    if (window->y == SDL_WINDOWPOS_CENTERED) {
        y = (dispdata->ch - window->h) / 2;
    } else if (window->y == SDL_WINDOWPOS_UNDEFINED) {
        y = 0;
    } else {
        y = window->y;
    }
    if (window->flags & SDL_WINDOW_FULLSCREEN) {
        x = 0;
        y = 0;
    }

    DirectFB_WM_AdjustWindowLayout(window);

    /* Create Window */
    desc.flags =
        DWDESC_WIDTH | DWDESC_HEIGHT | DWDESC_PIXELFORMAT | DWDESC_POSX
        | DWDESC_POSY | DWDESC_SURFACE_CAPS;
    desc.posx = x;
    desc.posy = y;
    desc.width = windata->size.w;
    desc.height = windata->size.h;
    desc.pixelformat = dispdata->pixelformat;
    desc.surface_caps = DSCAPS_PREMULTIPLIED;

    /* Create the window. */
    SDL_DFB_CHECKERR(dispdata->layer->CreateWindow(dispdata->layer, &desc,
                                                   &windata->window));

    /* Set Options */
    windata->window->GetOptions(windata->window, &wopts);

    if (window->flags & SDL_WINDOW_RESIZABLE)
        wopts |= DWOP_SCALE;
    else
        wopts |= DWOP_KEEP_SIZE;

    if (window->flags & SDL_WINDOW_FULLSCREEN) {
        wopts |= DWOP_KEEP_POSITION | DWOP_KEEP_STACKING | DWOP_KEEP_SIZE;
        windata->window->SetStackingClass(windata->window, DWSC_UPPER);
    }
    windata->window->SetOptions(windata->window, wopts);

    /* See what we got */
    SDL_DFB_CHECKERR(DirectFB_WM_GetClientSize
                     (_this, window, &window->w, &window->h));

    /* Get the window's surface. */
    SDL_DFB_CHECKERR(windata->window->GetSurface(windata->window,
                                                 &windata->window_surface));
    /* And get a subsurface for rendering */
    SDL_DFB_CHECKERR(windata->window_surface->
                     GetSubSurface(windata->window_surface, &windata->client,
                                   &windata->surface));

    windata->window->SetOpacity(windata->window, 0xFF);

    /* Create Eventbuffer */
    SDL_DFB_CHECKERR(windata->window->CreateEventBuffer(windata->window,
                                                        &windata->
                                                        eventbuffer));
    SDL_DFB_CHECKERR(windata->window->
                     EnableEvents(windata->window, DWET_ALL));

    /* Create a font */
    /* FIXME: once during Video_Init */
    if (windata->is_managed) {
        DFBFontDescription fdesc;

        fdesc.flags = DFDESC_HEIGHT;
        fdesc.height = windata->theme.font_size;
        font = NULL;
        SDL_DFB_CHECK(devdata->
                      dfb->CreateFont(devdata->dfb, windata->theme.font,
                                      &fdesc, &font));
        windata->window_surface->SetFont(windata->window_surface, font);
        SDL_DFB_RELEASE(font);
    }

    /* Make it the top most window. */
    windata->window->RaiseToTop(windata->window);

    /* remember parent */
    windata->window = window;

    /* Add to list ... */

    windata->next = devdata->firstwin;
    windata->opacity = 0xFF;
    devdata->firstwin = windata;

    /* Draw Frame */
    DirectFB_WM_RedrawLayout(window);

    return 0;
  error:
    SDL_DFB_RELEASE(windata->window);
    SDL_DFB_RELEASE(windata->surface);
    return -1;
}

int
DirectFB_CreateWindowFrom(_THIS, SDL_Window * window, const void *data)
{
    SDL_Unsupported();
    return -1;
}

void
DirectFB_SetWindowTitle(_THIS, SDL_Window * window)
{
    SDL_DFB_WINDOWDATA(window);

    if (windata->is_managed) {
        windata->wm_needs_redraw = 1;
    } else
        SDL_Unsupported();
}

void
DirectFB_SetWindowIcon(_THIS, SDL_Window * window, SDL_Surface * icon)
{
    SDL_DFB_DEVICEDATA(_this);
    SDL_DFB_WINDOWDATA(window);
    SDL_Surface *surface = NULL;
    DFBResult ret;

    if (icon) {
        SDL_PixelFormat format;
        DFBSurfaceDescription dsc;
        Uint32 *dest;
        Uint32 *p;
        int pitch, i;

        /* Convert the icon to ARGB for modern window managers */
        SDL_InitFormat(&format, 32, 0x00FF0000, 0x0000FF00, 0x000000FF,
                       0xFF000000);
        surface = SDL_ConvertSurface(icon, &format, 0);
        if (!surface) {
            return;
        }
        dsc.flags =
            DSDESC_WIDTH | DSDESC_HEIGHT | DSDESC_PIXELFORMAT | DSDESC_CAPS;
        dsc.caps = DSCAPS_VIDEOONLY;
        dsc.width = surface->w;
        dsc.height = surface->h;
        dsc.pixelformat = DSPF_ARGB;

        SDL_DFB_CHECKERR(devdata->dfb->CreateSurface(devdata->dfb, &dsc,
                                                     &windata->icon));

        SDL_DFB_CHECKERR(windata->icon->Lock(windata->icon, DSLF_WRITE,
                                             (void *) &dest, &pitch));

        p = surface->pixels;
        for (i = 0; i < surface->h; i++)
            memcpy((char *) dest + i * pitch,
                   (char *) p + i * surface->pitch, 4 * surface->w);

        windata->icon->Unlock(windata->icon);
        SDL_FreeSurface(surface);
    } else {
        SDL_DFB_RELEASE(windata->icon);
    }
    return;
  error:
    if (surface)
        SDL_FreeSurface(surface);
    SDL_DFB_RELEASE(windata->icon);
    return;
}

void
DirectFB_SetWindowPosition(_THIS, SDL_Window * window)
{
    SDL_DFB_WINDOWDATA(window);
    int x, y;

    if (window->y == SDL_WINDOWPOS_UNDEFINED)
        y = 0;
    else
        y = window->y;

    if (window->x == SDL_WINDOWPOS_UNDEFINED)
        x = 0;
    else
        x = window->x;

    if (window->flags & SDL_WINDOW_FULLSCREEN) {
        x = 0;
        y = 0;
    }
    DirectFB_WM_AdjustWindowLayout(window);
    windata->window->MoveTo(windata->window, x, y);
}

void
DirectFB_SetWindowSize(_THIS, SDL_Window * window)
{
    SDL_DFB_DEVICEDATA(_this);
    SDL_DFB_WINDOWDATA(window);
    int ret;

    if (!(window->flags & SDL_WINDOW_FULLSCREEN)) {
        int cw;
        int ch;

        /* Make sure all events are disabled for this operation ! */
        SDL_DFB_CHECKERR(windata->window->DisableEvents(windata->window,
                                                        DWET_ALL));

        SDL_DFB_CHECKERR(DirectFB_WM_GetClientSize(_this, window, &cw, &ch));

        if (cw != window->w || ch != window->h) {

            DirectFB_WM_AdjustWindowLayout(window);
            SDL_DFB_CHECKERR(windata->window->Resize(windata->window,
                                                     windata->size.w,
                                                     windata->size.h));
        }

        SDL_DFB_CHECKERR(windata->window->EnableEvents(windata->window,
                                                       DWET_ALL));

        SDL_DFB_CHECKERR(DirectFB_WM_GetClientSize
                         (_this, window, &window->w, &window->h));

        SDL_OnWindowResized(window);
    }
    return;
  error:
    windata->window->EnableEvents(windata->window, DWET_ALL);
    return;
}

void
DirectFB_ShowWindow(_THIS, SDL_Window * window)
{
    SDL_DFB_WINDOWDATA(window);

    windata->window->SetOpacity(windata->window, windata->opacity);

}

void
DirectFB_HideWindow(_THIS, SDL_Window * window)
{
    SDL_DFB_WINDOWDATA(window);

    windata->window->GetOpacity(windata->window, &windata->opacity);
    windata->window->SetOpacity(windata->window, 0);
}

void
DirectFB_RaiseWindow(_THIS, SDL_Window * window)
{
    SDL_DFB_WINDOWDATA(window);

    windata->window->RaiseToTop(windata->window);
    windata->window->RequestFocus(windata->window);
}

void
DirectFB_MaximizeWindow(_THIS, SDL_Window * window)
{
    SDL_DFB_WINDOWDATA(window);

    if (windata->is_managed) {
        DirectFB_WM_MaximizeWindow(_this, window);
    } else
        SDL_Unsupported();
}

void
DirectFB_MinimizeWindow(_THIS, SDL_Window * window)
{
    /* FIXME: Size to 32x32 ? */

    SDL_Unsupported();
}

void
DirectFB_RestoreWindow(_THIS, SDL_Window * window)
{
    SDL_DFB_WINDOWDATA(window);

    if (windata->is_managed) {
        DirectFB_WM_RestoreWindow(_this, window);
    } else
        SDL_Unsupported();
}

void
DirectFB_SetWindowGrab(_THIS, SDL_Window * window)
{
    SDL_DFB_WINDOWDATA(window);

    if ((window->flags & SDL_WINDOW_INPUT_GRABBED)) {
        windata->window->GrabPointer(windata->window);
        windata->window->GrabKeyboard(windata->window);
    } else {
        windata->window->UngrabPointer(windata->window);
        windata->window->UngrabKeyboard(windata->window);
    }
}

void
DirectFB_DestroyWindow(_THIS, SDL_Window * window)
{
    SDL_DFB_DEVICEDATA(_this);
    SDL_DFB_WINDOWDATA(window);
    DFB_WindowData *p;

    SDL_DFB_DEBUG("Trace\n");

    /* Some cleanups */
    windata->window->UngrabPointer(windata->window);
    windata->window->UngrabKeyboard(windata->window);

    windata->window_surface->SetFont(windata->window_surface, NULL);
    SDL_DFB_RELEASE(windata->icon);
    SDL_DFB_RELEASE(windata->eventbuffer);
    SDL_DFB_RELEASE(windata->surface);
    SDL_DFB_RELEASE(windata->window_surface);

    SDL_DFB_RELEASE(windata->window);

    /* Remove from list ... */

    p = devdata->firstwin;
    while (p && p->next != windata)
        p = p->next;
    if (p)
        p->next = windata->next;
    else
        devdata->firstwin = windata->next;
    SDL_free(windata);
    return;
}

SDL_bool
DirectFB_GetWindowWMInfo(_THIS, SDL_Window * window,
                         struct SDL_SysWMinfo * info)
{
    SDL_Unsupported();
    return SDL_FALSE;
}

void
DirectFB_AdjustWindowSurface(SDL_Window * window)
{
    SDL_DFB_WINDOWDATA(window);
    int adjust = windata->wm_needs_redraw;
    int cw, ch;
    int ret;

    DirectFB_WM_AdjustWindowLayout(window);

    SDL_DFB_CHECKERR(windata->
                     window_surface->GetSize(windata->window_surface, &cw,
                                             &ch));
    if (cw != windata->size.w || ch != windata->size.h) {
        adjust = 1;
    }

    if (adjust) {
#if DFB_VERSION_ATLEAST(1,2,1)
        SDL_DFB_CHECKERR(windata->window->ResizeSurface(windata->window,
                                                        windata->size.w,
                                                        windata->size.h));
        SDL_DFB_CHECKERR(windata->surface->MakeSubSurface(windata->surface,
                                                          windata->
                                                          window_surface,
                                                          &windata->client));
#else
        DFBWindowOptions opts;

        SDL_DFB_CHECKERR(windata->window->GetOptions(windata->window, &opts));
        /* recreate subsurface */
        SDL_DFB_RELEASE(windata->surface);

        if (opts & DWOP_SCALE)
            SDL_DFB_CHECKERR(windata->window->ResizeSurface(windata->window,
                                                            windata->size.w,
                                                            windata->size.h));
        SDL_DFB_CHECKERR(windata->window_surface->
                         GetSubSurface(windata->window_surface,
                                       &windata->client, &windata->surface));
#endif
        DirectFB_WM_RedrawLayout(window);
    }
  error:
    return;
}
