#ifdef TARGET_WII

#include <grrlib.h>
#include "gfx_wii.h"

// Change this. C3D stands for citro3D, the render for the 3ds port.
static C3D_RenderTarget* sTarget;

// This is needed on 3DS for different rendering modes.
Gfx3DSMode gGfx3DSMode;

// To remove. This checks if you're using a new 3DS or a normal one.
static bool checkN3DS()
{
    bool isNew3DS = false;

	if (R_SUCCEEDED(APT_CheckNew3DS(&isNew3DS)))
		return isNew3DS;

	return false;
}

// Initialize GFXs
static void gfx_wii_init(void) 
{
    if (checkN3DS())
		osSetSpeedupEnable(true);

    gfxInitDefault();
    consoleInit(GFX_BOTTOM, NULL);
    C3D_Init(C3D_DEFAULT_CMDBUF_SIZE);

// Changes the rendering modes I was talking about
    bool useAA = false;
#ifdef N3DS_USE_ANTIALIASING
    useAA = true;
#endif
    bool useWide = false;
#ifdef N3DS_USE_WIDE_800PX
    u8 model;
    CFGU_GetSystemModel(&model);
    useWide = model != 3; //wide is not possible on o2ds
#endif

    u32 transferFlags = 
        GX_TRANSFER_FLIP_VERT(0) | 
        GX_TRANSFER_OUT_TILED(0) | 
        GX_TRANSFER_RAW_COPY(0) |
	    GX_TRANSFER_IN_FORMAT(GX_TRANSFER_FMT_RGBA8) | 
        GX_TRANSFER_OUT_FORMAT(GX_TRANSFER_FMT_RGB8);

    if (useAA && !useWide)
        transferFlags |= GX_TRANSFER_SCALING(GX_TRANSFER_SCALE_XY);
    else if (useAA && useWide)
        transferFlags |= GX_TRANSFER_SCALING(GX_TRANSFER_SCALE_X);
    else
        transferFlags |= GX_TRANSFER_SCALING(GX_TRANSFER_SCALE_NO);

    int width = useAA || useWide ? 800 : 400;
    int height = useAA ? 480 : 240;

    sTarget = C3D_RenderTargetCreate(height, width, GPU_RB_RGBA8, GPU_RB_DEPTH24_STENCIL8);
	C3D_RenderTargetSetOutput(sTarget, GFX_TOP, GFX_LEFT, transferFlags);

    if (!useAA && !useWide)
        gGfx3DSMode = GFX_3DS_MODE_NORMAL;
    else if (useAA && !useWide)
        gGfx3DSMode = GFX_3DS_MODE_AA_22;
    else if (!useAA && useWide)
        gGfx3DSMode = GFX_3DS_MODE_WIDE;
    else
        gGfx3DSMode = GFX_3DS_MODE_WIDE_AA_12;

    if (useWide)
        gfxSetWide(true);
}

// The main loop that continuously calls functions to display things on the screen.
static void gfx_wii_main_loop(void (*run_one_game_iter)(void)) 
{
    while (aptMainLoop())
        run_one_game_iter();

    ndspExit();
    C3D_Fini();
	gfxExit();
}

// Self explanatory. To change.
static void gfx_wii_get_dimensions(uint32_t *width, uint32_t *height) 
{
    *width = 400;
    *height = 240;
}

static void gfx_wii_handle_events(void) 
{
}

// This starts every frame
static bool gfx_wii_start_frame(void)
{
    C3D_FrameBegin(C3D_FRAME_SYNCDRAW);
    C3D_RenderTargetClear(sTarget, C3D_CLEAR_ALL, 0x000000FF, 0xFFFFFFFF);
	C3D_FrameDrawOn(sTarget);
    return true;
}

// Swap between buffers.
static void gfx_wii_swap_buffers_begin(void) 
{
    C3D_FrameEnd(0);
    if(C3D_GetProcessingTime() < 1000.0f / 60.f)
        gspWaitForVBlank();
}

static void gfx_wii_swap_buffers_end(void) 
{
}

static double gfx_wii_get_time(void) 
{
    return 0.0;
}

// This is the list of every function on this file.
struct GfxWindowManagerAPI gfx_wii =
{
    gfx_wii_init,
    gfx_wii_main_loop,
    gfx_wii_get_dimensions,
    gfx_wii_handle_events,
    gfx_wii_start_frame,
    gfx_wii_swap_buffers_begin,
    gfx_wii_swap_buffers_end,
    gfx_wii_get_time
};

#endif