#include "Core.h"
#if defined CC_BUILD_XBOX360
#include "Window.h"
#include "Platform.h"
#include "Input.h"
#include "Event.h"
#include "Graphics.h"
#include "String.h"
#include "Funcs.h"
#include "Bitmap.h"
#include "Errors.h"
#include "ExtMath.h"
#include <xenos/xenos.h>
#include <input/input.h>
#include <usb/usbmain.h>

static cc_bool launcherMode;

struct _DisplayData DisplayInfo;
struct _WindowData WindowInfo;

// https://github.com/Free60Project/libxenon/blob/71a411cddfc26c9ccade08d054d87180c359797a/libxenon/drivers/console/console.c#L47
struct ati_info {
	uint32_t unknown1[4];
	uint32_t base;
	uint32_t unknown2[8];
	uint32_t width;
	uint32_t height;
} __attribute__ ((__packed__)) ;

void Window_Init(void) {
	struct ati_info* ai = (struct ati_info*)0xec806100ULL;
	
	DisplayInfo.Width  = ai->width;
	DisplayInfo.Height = ai->height;
	DisplayInfo.ScaleX = 1;
	DisplayInfo.ScaleY = 1;
	
	Window_Main.Width   = ai->width;
	Window_Main.Height  = ai->height;
	Window_Main.Focused = true;
	Window_Main.Exists  = true;

	Input.Sources = INPUT_SOURCE_GAMEPAD;
	
	usb_init();
	usb_do_poll();
	
	//xenon_ata_init();
	//xenon_atapi_init();
}

void Window_Free(void) { }

void Window_Create2D(int width, int height) { launcherMode = true;  }
void Window_Create3D(int width, int height) { launcherMode = false; }

void Window_SetTitle(const cc_string* title) { }
void Clipboard_GetText(cc_string* value) { }
void Clipboard_SetText(const cc_string* value) { }

int Window_GetWindowState(void) { return WINDOW_STATE_FULLSCREEN; }
cc_result Window_EnterFullscreen(void) { return 0; }
cc_result Window_ExitFullscreen(void)  { return 0; }
int Window_IsObscured(void)            { return 0; }

void Window_Show(void) { }
void Window_SetSize(int width, int height) { }

void Window_RequestClose(void) {
	/* TODO implement */
}


/*########################################################################################################################*
*----------------------------------------------------Input processing-----------------------------------------------------*
*#########################################################################################################################*/
/*
struct controller_data_s
{
	signed short s1_x, s1_y, s2_x, s2_y;
	int s1_z, s2_z, lb, rb, start, back, a, b, x, y, up, down, left, right;
	unsigned char lt, rt;
	int logo;
};
*/

static void HandleButtons(struct controller_data_s* pad) {
	Gamepad_SetButton(CCPAD_L, pad->lb);
	Gamepad_SetButton(CCPAD_R, pad->rb);
	
	Gamepad_SetButton(CCPAD_A, pad->a);
	Gamepad_SetButton(CCPAD_B, pad->b);
	Gamepad_SetButton(CCPAD_X, pad->x);
	Gamepad_SetButton(CCPAD_Y, pad->y);
	
	Gamepad_SetButton(CCPAD_START,  pad->start);
	Gamepad_SetButton(CCPAD_SELECT, pad->back);
	
	Gamepad_SetButton(CCPAD_LEFT,   pad->left);
	Gamepad_SetButton(CCPAD_RIGHT,  pad->right);
	Gamepad_SetButton(CCPAD_UP,     pad->up);
	Gamepad_SetButton(CCPAD_DOWN,   pad->down);
}

void Window_ProcessEvents(double delta) {
	usb_do_poll();
	
	struct controller_data_s pad;
 	int res = get_controller_data(&pad, 0);
 	if (res == 0) return;
 	
 	HandleButtons(&pad);
}

void Cursor_SetPosition(int x, int y) { } // Makes no sense for Xbox

void Window_EnableRawMouse(void)  { Input.RawMode = true;  }
void Window_DisableRawMouse(void) { Input.RawMode = false; }
void Window_UpdateRawMouse(void)  { }


/*########################################################################################################################*
*------------------------------------------------------Framebuffer--------------------------------------------------------*
*#########################################################################################################################*/
void Window_AllocFramebuffer(struct Bitmap* bmp) {
	bmp->scan0 = (BitmapCol*)Mem_Alloc(bmp->width * bmp->height, 4, "window pixels");
}

void Window_DrawFramebuffer(Rect2D r, struct Bitmap* bmp) {
	return;
	//void* fb = XVideoGetFB();
	//XVideoWaitForVBlank();

	/*cc_uint32* src = (cc_uint32*)bmp->scan0 + r.X;
	cc_uint32* dst = (cc_uint32*)fb           + r.X;

	for (int y = r.Y; y < r.Y + r.height; y++) 
	{
		Mem_Copy(dst + y * bmp->width, src + y * bmp->width, r.width * 4);
	}*/
}

void Window_FreeFramebuffer(struct Bitmap* bmp) {
	Mem_Free(bmp->scan0);
}


/*########################################################################################################################*
*------------------------------------------------------Soft keyboard------------------------------------------------------*
*#########################################################################################################################*/
void OnscreenKeyboard_Open(struct OpenKeyboardArgs* args) { }
void OnscreenKeyboard_SetText(const cc_string* text) { }
void OnscreenKeyboard_Draw2D(Rect2D* r, struct Bitmap* bmp) { }
void OnscreenKeyboard_Draw3D(void) { }
void OnscreenKeyboard_Close(void) { /* TODO implement */ }


/*########################################################################################################################*
*-------------------------------------------------------Misc/Other--------------------------------------------------------*
*#########################################################################################################################*/
void Window_ShowDialog(const char* title, const char* msg) {
	/* TODO implement */
	Platform_LogConst(title);
	Platform_LogConst(msg);
}

cc_result Window_OpenFileDialog(const struct OpenFileDialogArgs* args) {
	return ERR_NOT_SUPPORTED;
}

cc_result Window_SaveFileDialog(const struct SaveFileDialogArgs* args) {
	return ERR_NOT_SUPPORTED;
}
#endif
