#include <strsafe.h>
#include "main.h"
#include <shellapi.h>

#include "../nu/DialogSkinner.h"
#include "../nu/ListView.h"

#include "../../General/gen_ml/ml_ipc.h"
#include "../../General/gen_ml/menu.h"

#include "../WAT/WAT.h"


#ifdef _DEBUG
constexpr auto FANZONE_BASE_URL = L"https://player-stg.winamp.com/fanzone/music?mtm_campaign=legendary_player";
#else
constexpr auto FANZONE_BASE_URL = L"https://player.winamp.com/fanzone/music?mtm_campaign=legendary_player";
#endif // _DEBUG

INT_PTR CALLBACK view_FANZONEDialogProc(HWND hwndDlg, UINT uMsg, WPARAM wParam,LPARAM lParam);
static W_ListView   m_fanzone_node;
static HWND         m_headerhwnd;
extern C_Config    *g_config;
extern char        *g_ext_list;
static int          customAllowed;
static viewButtons  view;

C_Config *g_wa_config = 0;
char     *g_ext_list  = 0;

// used for the send-to menu bits
static INT_PTR IPC_LIBRARY_SENDTOMENU;
static librarySendToMenuStruct s;
BOOL myMenu = FALSE;

extern HMENU g_context_menus, g_context_menus2;
extern HCURSOR hDragNDropCursor;

static int FANZONE_contextMenu( INT_PTR param1, HWND hHost, POINTS pts )
{
	return TRUE;
}

static int pluginHandleIpcMessage(int msg, int param) 
{
	return (int)SendMessage( plugin.hwndLibraryParent, WM_ML_IPC, param, msg );
}

INT_PTR fanzone_pluginMessageProc( int message_type, INT_PTR param1, INT_PTR param2, INT_PTR param3 )
{
	if ( message_type == ML_MSG_NO_CONFIG )
	{
		return TRUE;
	}
	else if ( message_type == ML_MSG_TREE_ONCREATEVIEW && param1 == fanzone_treeItem )
	{
		return (INT_PTR)WASABI_API_CREATEDIALOGW( IDD_VIEW_FANZONE, (HWND)param2, view_FANZONEDialogProc );
	}
	else if ( message_type == ML_MSG_NAVIGATION_CONTEXTMENU )
	{
		return FANZONE_contextMenu( param1, (HWND)param2, MAKEPOINTS( param3 ) );
	}
	else if ( message_type == ML_MSG_ONSENDTOSELECT || message_type == ML_MSG_TREE_ONDROPTARGET )
	{
		// set with droptarget defaults =)
		UINT_PTR type = 0, data = 0;

		if ( message_type == ML_MSG_ONSENDTOSELECT )
		{
			if ( param3 != (INT_PTR)fanzone_pluginMessageProc ) return 0;

			type = (int)param1;
			data = (int)param2;
		}
		else
		{
			if ( param1 != fanzone_treeItem ) return 0;

			type = (int)param2;
			data = (int)param3;

			if ( !data )
			{
				return ( type == ML_TYPE_ITEMRECORDLISTW || type == ML_TYPE_ITEMRECORDLIST ||
					type == ML_TYPE_FILENAMES || type == ML_TYPE_STREAMNAMES ||
					type == ML_TYPE_FILENAMESW || type == ML_TYPE_STREAMNAMESW ||
					type == ML_TYPE_CDTRACKS ||
					type == ML_TYPE_PLAYLIST || type == ML_TYPE_PLAYLISTS ) ? 1 : -1;
			}
		}
	}
	else if ( message_type == WM_WA_IPC )
	{

		int l_toto = 0;
	}
	else if ( message_type == IPC_SETVOLUME )
	{
		int curvol = IPC_GETVOLUME( plugin.hwndWinampParent );


		int l_toto = 0;
	}
	else if ( message_type == WINAMP_VOLUMEDOWN )
	{


		int l_toto = 0;
	}
	else if ( message_type == WINAMP_VOLUMEUP )
	{


		int l_toto = 0;
	}


	return 0;
}


static HRGN g_rgnUpdate = NULL;
static int offsetX = 0, offsetY = 0;

typedef struct _LAYOUT
{
	INT		id;
	HWND	hwnd;
	INT		x;
	INT		y;
	INT		cx;
	INT		cy;
	DWORD	flags;
	HRGN	rgn;
}
LAYOUT, PLAYOUT;

#define SETLAYOUTPOS(_layout, _x, _y, _cx, _cy) { _layout->x=_x; _layout->y=_y;_layout->cx=_cx;_layout->cy=_cy;_layout->rgn=NULL; }
#define SETLAYOUTFLAGS(_layout, _r)																						\
	{																													\
		BOOL fVis;																										\
		fVis = (WS_VISIBLE & (LONG)GetWindowLongPtr(_layout->hwnd, GWL_STYLE));											\
		if (_layout->x == _r.left && _layout->y == _r.top) _layout->flags |= SWP_NOMOVE;									\
		if (_layout->cx == (_r.right - _r.left) && _layout->cy == (_r.bottom - _r.top)) _layout->flags |= SWP_NOSIZE;	\
		if ((SWP_HIDEWINDOW & _layout->flags) && !fVis) _layout->flags &= ~SWP_HIDEWINDOW;								\
		if ((SWP_SHOWWINDOW & _layout->flags) && fVis) _layout->flags &= ~SWP_SHOWWINDOW;									\
	}

#define LAYOUTNEEEDUPDATE(_layout) ((SWP_NOMOVE | SWP_NOSIZE) != ((SWP_NOMOVE | SWP_NOSIZE | SWP_HIDEWINDOW | SWP_SHOWWINDOW) & _layout->flags))

#define GROUP_MIN			0x1
#define GROUP_MAX			0x2
#define GROUP_STATUSBAR		0x1
#define GROUP_MAIN			0x2

static void LayoutWindows(HWND hwnd, BOOL fRedraw, BOOL fUpdateAll = FALSE)
{
	static INT controls[] =
	{
		GROUP_STATUSBAR, GROUP_MAIN,  IDC_LIST_FANZONE
	};

	INT index;
	RECT rc, rg, ri;
	LAYOUT layout[ sizeof( controls ) / sizeof( controls[ 0 ] ) ], *pl;
	BOOL skipgroup;
	HRGN rgn = NULL;

	GetClientRect(hwnd, &rc);
	if ( rc.right == rc.left || rc.bottom == rc.top )
		return;

	if ( rc.right > WASABI_API_APP->getScaleX( 4 ) )
		rc.right -= WASABI_API_APP->getScaleX( 4 );

	SetRect(&rg, rc.left, rc.top, rc.right, rc.top);

	pl        = layout;
	skipgroup = FALSE;

	InvalidateRect(hwnd, NULL, TRUE);

	for ( index = 0; index < sizeof( controls ) / sizeof( *controls ); index++ )
	{
		if ( controls[ index ] >= GROUP_MIN && controls[ index ] <= GROUP_MAX ) // group id
		{
			skipgroup = FALSE;
			switch ( controls[ index ] )
			{
				case GROUP_MAIN:
					SetRect( &rg, rc.left + WASABI_API_APP->getScaleX( 1 ), rc.top, rc.right, rc.bottom );
					break;
			}
			continue;
		}

		if (skipgroup)
			continue;

		pl->id   = controls[ index ];
		pl->hwnd = GetDlgItem( hwnd, pl->id );
		if ( !pl->hwnd )
			continue;

		GetWindowRect( pl->hwnd, &ri );
		MapWindowPoints( HWND_DESKTOP, hwnd, (LPPOINT)&ri, 2 );
		pl->flags = SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOREDRAW | SWP_NOCOPYBITS;

		switch (pl->id)
		{
		case IDC_LIST_FANZONE:
			pl->flags |= (rg.top < rg.bottom) ? SWP_SHOWWINDOW : SWP_HIDEWINDOW;
			SETLAYOUTPOS(pl, rg.left, rg.top + WASABI_API_APP->getScaleY(1),
				rg.right - rg.left + WASABI_API_APP->getScaleY(1),
				(rg.bottom - rg.top) - WASABI_API_APP->getScaleY(2));
			break;
		}

		SETLAYOUTFLAGS( pl, ri );
		if ( LAYOUTNEEEDUPDATE( pl ) )
		{
			if ( SWP_NOSIZE == ( ( SWP_HIDEWINDOW | SWP_SHOWWINDOW | SWP_NOSIZE ) & pl->flags ) && ri.left == ( pl->x + offsetX ) && ri.top == ( pl->y + offsetY ) && IsWindowVisible( pl->hwnd ) )
			{
				SetRect( &ri, pl->x, pl->y, pl->cx + pl->x, pl->y + pl->cy );
				ValidateRect( hwnd, &ri );
			}
			pl++;
		}
		else if ((fRedraw || (!offsetX && !offsetY)) && IsWindowVisible(pl->hwnd)) 
		{
			ValidateRect(hwnd, &ri);
			if ( GetUpdateRect( pl->hwnd, NULL, FALSE ) )
			{
				if ( !rgn )
					rgn = CreateRectRgn( 0, 0, 0, 0 );

				GetUpdateRgn( pl->hwnd, rgn, FALSE );
				OffsetRgn( rgn, pl->x, pl->y );
				InvalidateRgn( hwnd, rgn, FALSE );
			}
		}
	}

	if (pl != layout)
	{
		LAYOUT *pc;
		HDWP hdwp = BeginDeferWindowPos( (INT)( pl - layout ) );
		for ( pc = layout; pc < pl && hdwp; pc++ )
		{
			hdwp = DeferWindowPos( hdwp, pc->hwnd, NULL, pc->x, pc->y, pc->cx, pc->cy, pc->flags );
		}

		if ( hdwp )
			EndDeferWindowPos( hdwp );

		if ( !rgn )
			rgn = CreateRectRgn( 0, 0, 0, 0 );

		if ( fRedraw )
		{
			GetUpdateRgn( hwnd, rgn, FALSE );
			for ( pc = layout; pc < pl && hdwp; pc++ )
			{
				if ( pc->rgn )
				{
					OffsetRgn( pc->rgn, pc->x, pc->y );
					CombineRgn( rgn, rgn, pc->rgn, RGN_OR );
				}
			}

			RedrawWindow( hwnd, NULL, rgn, RDW_INVALIDATE | RDW_UPDATENOW | RDW_ERASENOW | RDW_ALLCHILDREN );
		}

		if ( g_rgnUpdate )
		{
			GetUpdateRgn( hwnd, g_rgnUpdate, FALSE );
			for ( pc = layout; pc < pl && hdwp; pc++ )
			{
				if ( pc->rgn )
				{
					OffsetRgn( pc->rgn, pc->x, pc->y );
					CombineRgn( g_rgnUpdate, g_rgnUpdate, pc->rgn, RGN_OR );
				}
			}
		}

		for ( pc = layout; pc < pl && hdwp; pc++ )
			if ( pc->rgn )
				DeleteObject( pc->rgn );
	}

	if ( rgn )
		DeleteObject( rgn );

	ValidateRgn( hwnd, NULL );
}

static BOOL FANZONE_OnDisplayChange()
{
	ListView_SetTextColor( m_fanzone_node.getwnd(), dialogSkinner.Color( WADLG_ITEMFG ) );
	ListView_SetBkColor( m_fanzone_node.getwnd(), dialogSkinner.Color( WADLG_ITEMBG ) );
	ListView_SetTextBkColor( m_fanzone_node.getwnd(), dialogSkinner.Color( WADLG_ITEMBG ) );
	
	m_fanzone_node.SetFont( dialogSkinner.GetFont() );
	
	LayoutWindows( m_hwnd, TRUE );

	// Display the modal windows
	ShowWindow( m_fanzone_node.getwnd(), SW_SHOW );
	UpdateWindow( m_fanzone_node.getwnd() );

	return 0;
}


enum
{
	BPM_ECHO_WM_COMMAND = 0x1, // send WM_COMMAND and return value
	BPM_WM_COMMAND      = 0x2, // just send WM_COMMAND
};

static BOOL FANZONE_OnCommand( HWND hwnd, int id, HWND hwndCtl, UINT codeNotify )
{
	return FALSE;
}

static BOOL FANZONE_OnDestroy(HWND hwnd)
{
	m_hwnd = 0;

	return FALSE;
}

static BOOL FANZONE_OnNotify(HWND hwnd, NMHDR *notification)
{
	if (notification->idFrom == IDC_LIST_FANZONE)
	{
		if (notification->code == LVN_BEGINDRAG)
		{
			SetCapture(hwnd);
		}
	}
	return FALSE;
}

static BOOL FANZONE_OnInitDialog(HWND hwndDlg, HWND hwndFocus, LPARAM lParam)
{
	m_hwnd = hwndDlg;

	m_fanzone_node.setwnd(GetDlgItem(hwndDlg, IDC_LIST_FANZONE));
	

	if (!view.play)
	{
		SENDMLIPC(plugin.hwndLibraryParent, ML_IPC_GET_VIEW_BUTTON_TEXT, (WPARAM)&view);
	}


	FANZONE_OnDisplayChange();

	m_headerhwnd = ListView_GetHeader( m_fanzone_node.getwnd() );

	// v5.66+ - re-use the old predixis parts so the button can be used functionally via ml_enqplay
	//			pass the hwnd, button id and plug-in id so the ml plug-in can check things as needed
	customAllowed = FALSE;

	MLSKINWINDOW l_ml_skin_window = {0};
	l_ml_skin_window.skinType     = SKINNEDWND_TYPE_DIALOG;
	l_ml_skin_window.style        = SWS_USESKINCOLORS | SWS_USESKINCURSORS | SWS_USESKINFONT;
	l_ml_skin_window.hwndToSkin   = m_hwnd;
	MLSkinWindow( plugin.hwndLibraryParent, &l_ml_skin_window );

	//l_ml_skin_window.skinType     = SKINNEDWND_TYPE_STATIC;
	//l_ml_skin_window.style        = SWS_USESKINCOLORS | SWS_USESKINCURSORS | SWS_USESKINFONT;
	//l_ml_skin_window.hwndToSkin   = m_hwnd;
	//MLSkinWindow( mediaLibrary.library, &l_ml_skin_window );

	ShellExecuteW(NULL, L"open", FANZONE_BASE_URL, NULL, NULL, SW_SHOWNORMAL);

	delete g_wa_config;

	SetTimer( m_hwnd, 100, 15, NULL );
	

	return TRUE;
}



INT_PTR CALLBACK view_FANZONEDialogProc(HWND hwndDlg, UINT uMsg, WPARAM wParam,LPARAM lParam) 
{
	INT_PTR a = dialogSkinner.Handle(hwndDlg, uMsg, wParam, lParam);
	if (a) return a;

	switch(uMsg) 
	{
		HANDLE_MSG(hwndDlg, WM_INITDIALOG, FANZONE_OnInitDialog);
		HANDLE_MSG(hwndDlg, WM_COMMAND,    FANZONE_OnCommand);
		HANDLE_MSG(hwndDlg, WM_DESTROY,    FANZONE_OnDestroy);

		case WM_WINDOWPOSCHANGED:
			if ((SWP_NOSIZE | SWP_NOMOVE) != ((SWP_NOSIZE | SWP_NOMOVE) & ((WINDOWPOS*)lParam)->flags) || 
				(SWP_FRAMECHANGED & ((WINDOWPOS*)lParam)->flags))
			{
				LayoutWindows(hwndDlg, !(SWP_NOREDRAW & ((WINDOWPOS*)lParam)->flags));
			}
			return 0;

		case WM_USER + 0x200:
			SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, 1); // yes, we support no - redraw resize
			return TRUE;

		case WM_USER + 0x201:
			offsetX = (short)LOWORD(wParam);
			offsetY = (short)HIWORD(wParam);
			g_rgnUpdate = (HRGN)lParam;
			return TRUE;

		case WM_PAINT:
			{
				int tab[] = { IDC_LIST_FANZONE | DCW_SUNKENBORDER };
				dialogSkinner.Draw(hwndDlg, tab, sizeof(tab) / sizeof(tab[0]));
			}
			return 0;

		case WM_INITMENUPOPUP:
			if (wParam && (HMENU)wParam == s.build_hMenu && s.mode==1)
			{
				myMenu = TRUE;
				if(SendMessage(plugin.hwndWinampParent, WM_WA_IPC, (WPARAM)&s, IPC_LIBRARY_SENDTOMENU)==0xffffffff)
					s.mode=2;
				myMenu = FALSE;
			}
			return 0;

		case WM_DISPLAYCHANGE:
			return FANZONE_OnDisplayChange();

		case WM_NOTIFY:
			return FANZONE_OnNotify(hwndDlg, (LPNMHDR)lParam);
	}

	return FALSE;
}