#include <amxmodx>
#include <amxmisc>
#include <nvault>

#define MAX_PLAYERS	32
#define MAX_GROUPS	10
#define MAX_MEDIA	20

#define STR_SIZE_XSM	32
#define STR_SIZE_SML	64
#define STR_SIZE_MED	128
#define STR_SIZE_LRG	256
#define STR_SIZE_XLG	512
#define STR_SIZE_XXL	1024
#define STR_SIZE_XXX	2048

new const g_media_list_filename[] 	= "amp_medialist.ini"
new const g_media_player_filename[]	= "amp_player.html"
new const g_media_stats_vaultname[]	= "amp_stats"

#define str_size(%1) sizeof(%1) - 1

enum
{
	GROUP = 0,
	MEDIA
}

enum
{
	STR_GROUP_NAME = 0,
	STR_MEDIA_NAME,
	STR_MEDIA_URL,
	STR_MEDIA_RATINGS
}

new const FIND[4][] =
{
	"[GROUP_NAME]",
	"[MEDIA_NAME]",
	"[MEDIA_URL]",
	"[MEDIA_RATINGS]"
}

new g_menuposition[MAX_PLAYERS+1][2]
new g_curmediaplaying[MAX_PLAYERS+1][2]

new g_hudsync
new g_numofgroup
new g_numofmedia[MAX_GROUPS]
new g_media_player[STR_SIZE_MED]
new g_group_names[MAX_GROUPS][STR_SIZE_XSM]
new g_media_names[MAX_GROUPS][MAX_MEDIA][STR_SIZE_XSM]
new g_media_urls[MAX_GROUPS][MAX_MEDIA][STR_SIZE_LRG]

static const PLUGIN_NAME[] 	= "Advance Media Player"
static const PLUGIN_AUTHOR[] 	= "Cheap_Suit"
static const PLUGIN_VERSION[]	= "3.0"

public plugin_init()
{
	register_plugin(PLUGIN_NAME, PLUGIN_VERSION, PLUGIN_AUTHOR)
	register_cvar(PLUGIN_NAME, PLUGIN_VERSION, FCVAR_SPONLY|FCVAR_SERVER)
	register_menucmd(register_menuid("media_group"), 1023, "action_grouplist")
	register_menucmd(register_menuid("media_list"),  1023, "action_medialist")
	register_clcmd("say", "cmd_say")
	
	register_media()
	g_hudsync = CreateHudSyncObj() 
	set_task(1.0, "task_hud", _, _, _, "b")
}

public client_putinserver(id)
{
	g_curmediaplaying[id][GROUP] = -1
	g_curmediaplaying[id][MEDIA] = -1
}

public task_hud()
{
	static players[32]
	new num, id
	
	get_players(players, num, "bch")
	set_hudmessage(255, 255, 255, 0.0, 0.13, _, _, 1.1, _, _, 1)

	for(new i = 0; i < num; ++i) 
	{
		id = players[i]
		
		if(g_curmediaplaying[id][MEDIA] != -1)
		{
			ShowSyncHudMsg(id, g_hudsync, "Playing Media: %s^nCommands:^n/ratemedia 1-5^n/reloadmedia^n/stopmedia^n", 
			g_media_names[g_curmediaplaying[id][GROUP]][g_curmediaplaying[id][MEDIA]])
		}
		else
			ShowSyncHudMsg(players[i], g_hudsync, "Playing Media: <none>^nCommands:^n/playmedia^n")
	}
}

public cmd_say(id)
{
	static say_args[STR_SIZE_MED]
	read_args(say_args, str_size(say_args))
	remove_quotes(say_args)
	
	if(say_args[0] != '/')
		return PLUGIN_CONTINUE
	
	if(equali(say_args, "/playmedia"))
	{
		display_grouplist(id, g_menuposition[id][GROUP] = 0)
		
		return PLUGIN_HANDLED
	}
	else if(equali(say_args, "/stopmedia"))
	{
		g_curmediaplaying[id][GROUP] = -1
		g_curmediaplaying[id][MEDIA] = -1
		
		static motd[STR_SIZE_XLG]
		new len = format(motd, str_size(motd), "<html><head><style type=^"text/css^">pre{color:#FFB000;}body{background:#000000;margin-left:8px;margin-top:0px;}</style></head><pre><body>")
		len += format(motd[len], str_size(motd) - len, "<center>Stopped media. This has been brought you by %s.^n", PLUGIN_NAME)
		len += format(motd[len], str_size(motd) - len, "<center>You can get this plugin @ amxmodx.org.^n")
		
		show_motd(id, motd, PLUGIN_NAME)
		
		return PLUGIN_HANDLED
	}
	else if(containi(say_args, "/ratemedia") != -1)
	{
		if(g_curmediaplaying[id][MEDIA] == -1)
		{
			client_print(id, print_chat, "You are not listening to any media.")
			return PLUGIN_HANDLED
		}
		
		static text[20]
		static trash[2]
		static rate[3]
		
		read_argv(1, text, str_size(text))
		strbreak(text, trash, str_size(trash), rate, str_size(rate))
		
		if(!isdigit(rate[0]) || strlen(rate) == 0 || str_to_num(rate) > 5)
			client_print(id, print_chat, "Rate scale is from 1 to 5")
		else
		{
			save_data(id, str_to_num(rate))
			client_print(id, print_chat, "You have rated Media: %s - %s stars.", g_media_names[g_curmediaplaying[id][GROUP]][g_curmediaplaying[id][MEDIA]], rate)
		}
		return PLUGIN_HANDLED
	}
	else if(equali(say_args, "/reloadmedia"))
	{
		if(g_curmediaplaying[id][MEDIA] == -1)
			client_print(id, print_chat, "You are not listening to any media.")
		else
			play_media(id, g_curmediaplaying[id][MEDIA], g_curmediaplaying[id][GROUP])
		
		return PLUGIN_HANDLED
	}
	return PLUGIN_CONTINUE
}

display_grouplist(id, pos)
{
	if(pos < 0)
		return

	new maxtotal = g_numofgroup
		
	new start = pos * 8
  	if(start >= maxtotal)
    		start = pos = g_menuposition[id][GROUP]
	
	static menubody[STR_SIZE_XLG]
  	new len = format(menubody, str_size(menubody), "Select Media Group^n^n")
	
  	new end = start + 8
  	new keys = MENU_KEY_0

	if(end > maxtotal)
    		end = maxtotal

	new b = 0
  	for(new a = start; a < end; ++a) 
	{
		keys |= (1<<b)
		
		len += format(menubody[len], str_size(menubody) - len, "%d. %s^n", ++b, g_group_names[a])
  	}

  	if(end != maxtotal)
	{
    		format(menubody[len], str_size(menubody) - len, "^n9. %s...^n0. %s", "More", pos ? "Back" : "Exit")
    		keys |= MENU_KEY_9
  	}
  	else
		format(menubody[len], str_size(menubody) - len, "^n0. %s", pos ? "Back" : "Exit")
		
  	show_menu(id, keys, menubody, -1, "media_group")
}

public action_grouplist(id, key)
{
	switch(key) 
	{
    		case 8:	display_grouplist(id, ++g_menuposition[id][GROUP])
		case 9:	display_grouplist(id, --g_menuposition[id][GROUP])
    		default:display_medialist(id, g_menuposition[id][MEDIA] = 0, g_menuposition[id][GROUP] = (g_menuposition[id][GROUP] * 8 + key))
	}
	return PLUGIN_HANDLED
}

display_medialist(id, pos, group)
{
	if(pos < 0)
	{
		display_grouplist(id, g_menuposition[id][GROUP] = 0)
		return
	}
	
	new maxtotal = g_numofmedia[group]

	new start = pos * 8
  	if(start >= maxtotal)
    		start = pos = g_menuposition[id][MEDIA]
	
	static menubody[STR_SIZE_XLG]
  	new len = format(menubody, str_size(menubody), "%s^n^n", g_group_names[group])
	
  	new end = start + 8
  	new keys = MENU_KEY_0

	if(end > maxtotal)
    		end = maxtotal

	new b = 0
  	for(new a = start; a < end; ++a) 
	{
		keys |= (1<<b)
		len += format(menubody[len], str_size(menubody), "%d. %s^n", ++b, g_media_names[group][a])
  	}

  	if(end != maxtotal)
	{
    		format(menubody[len], str_size(menubody), "^n9. %s...^n0. %s", "More", pos ? "Back" : "Back to group list")
    		keys |= MENU_KEY_9
  	}
  	else
		format(menubody[len], str_size(menubody), "^n0. %s", pos ? "Back" : "Back to group list")
		
  	show_menu(id, keys, menubody, -1, "media_list")
}

public action_medialist(id, key)
{
	switch(key) 
	{
    		case 8: display_medialist(id, ++g_menuposition[id][MEDIA], g_menuposition[id][GROUP])
		case 9: display_medialist(id, --g_menuposition[id][MEDIA], g_menuposition[id][GROUP])
    		default:play_media(id, g_menuposition[id][GROUP], (g_menuposition[id][MEDIA] * 8 + key))
	}
	return PLUGIN_HANDLED
}

play_media(id, group_id, media_id)
{
	if(!file_exists(g_media_player))
		return
	
	g_curmediaplaying[id][GROUP] = group_id
	g_curmediaplaying[id][MEDIA] = media_id
	
	new player[STR_SIZE_XXL]
	new motd[STR_SIZE_XXX]
	new line, length
	
	while(read_file(g_media_player, line++, player, str_size(player), length))
		add(motd, str_size(motd), player)

	replace_all(motd, str_size(motd), FIND[STR_GROUP_NAME], g_group_names[group_id])
	replace_all(motd, str_size(motd), FIND[STR_MEDIA_NAME], g_media_names[group_id][media_id])
	replace_all(motd, str_size(motd), FIND[STR_MEDIA_URL], g_media_urls[group_id][media_id])
	
	static ratings[STR_SIZE_XSM]
	get_media_ratings(g_media_names[group_id][media_id], ratings, str_size(ratings))
	replace_all(motd, str_size(motd), FIND[STR_MEDIA_RATINGS], ratings)
	
	show_motd(id, motd, PLUGIN_NAME)
}

stock get_media_ratings(media_name[], string[], len)
{
	new vault_id = nvault_open(g_media_stats_vaultname)
	if(vault_id == INVALID_HANDLE)
		log_amx("Enable to open nvault file: %s", g_media_stats_vaultname)
	
	static value[STR_SIZE_XSM]
	static key[STR_SIZE_MED]
	
	new total = 0, score = 0, timestamp, ratings
	
	format(key, str_size(key), "%s-TOTAL", media_name)
	replace_all(key, sizeof(key), " ", "_")
		
	if(nvault_lookup(vault_id, key, value, str_size(value), timestamp))
		total = str_to_num(value)
	
	format(key, str_size(key), "%s-SCORE", media_name)
	replace_all(key, sizeof(key), " ", "_")
	
	if(nvault_lookup(vault_id, key, value, str_size(value), timestamp))
		score = str_to_num(value)

	ratings = format(string, len, "none")
	if(total != 0 && score != 0)
	{
		new totalstars = floatround(float(score) / float(total))
		
		new stars[5]
		for(new i = 0; i < totalstars; ++i)
			copy(stars[i], str_size(stars), "*")
		
		ratings = format(string, len, stars)
	}
	return ratings
}

save_data(id, data)
{
	new vault_id = nvault_open(g_media_stats_vaultname)
	if(vault_id == INVALID_HANDLE)
		log_amx("Enable to open nvault file: %s", g_media_stats_vaultname)
	
	static value[STR_SIZE_XSM]
	static key[STR_SIZE_MED]
	new timestamp, addvalue = 0
	
	static media_name[STR_SIZE_SML]
	format(media_name, str_size(media_name), g_media_names[g_curmediaplaying[id][GROUP]][g_curmediaplaying[id][MEDIA]])
	
	format(key, str_size(key), "%s-TOTAL", media_name)
	replace_all(key, sizeof(key), " ", "_")
		
	if(nvault_lookup(vault_id, key, value, str_size(value), timestamp))
		addvalue = str_to_num(value) + 1
	else
		addvalue = 1
				
	num_to_str(addvalue, value, str_size(value))
	nvault_pset(vault_id, key, value)
			
	format(key, str_size(key), "%s-SCORE", media_name)
	replace_all(key, sizeof(key), " ", "_")
			
	if(nvault_lookup(vault_id, key, value, str_size(value), timestamp))
		addvalue = str_to_num(value) + data
	else
		addvalue = data
				
	num_to_str(addvalue, value, str_size(value))
	nvault_pset(vault_id, key, value)
	
	nvault_close(vault_id)
}

register_media()
{
	static configs_dir[STR_SIZE_SML]
	static file_text[STR_SIZE_XXX]
	new len = 0
	
	get_localinfo("amxx_configsdir", configs_dir, str_size(configs_dir))
	
	format(g_media_player, str_size(g_media_player), "%s/%s", configs_dir, g_media_player_filename)
	if(!file_exists(g_media_player))
	{
		len = format(file_text, str_size(file_text), "<html><head><style type=^"text/css^">pre{color:#FFB000;}body{background:#000000;margin-left:8px;margin-top:0px;}</style></head><pre><body>")
		len += format(file_text[len], str_size(file_text) - len, "<center><b>Media:</b> ([GROUP_NAME]) [MEDIA_NAME]^n")
		len += format(file_text[len], str_size(file_text) - len, "<center><b>Ratings:[MEDIA_RATINGS]</b>^n")
		len += format(file_text[len], str_size(file_text) - len, "<center>Note: Selected media may take long to load.^n")
		len += format(file_text[len], str_size(file_text) - len, "<center>You may close this motd, the media will keep playing.^n")
		len += format(file_text[len], str_size(file_text) - len, "<center><OBJECT ID=^"MediaPlayer1^" width=400 height=144^n")
		len += format(file_text[len], str_size(file_text) - len, "classid=^"CLSID:22D6F312-B0F6-11D0-94AB-0080C74C7E95^"^n")
		len += format(file_text[len], str_size(file_text) - len, "CODEBASE=^"http://activex.microsoft.com/activex/controls/mplayer/en/nsmp2inf.cab#Version=6,4,5,715^"^n")
		len += format(file_text[len], str_size(file_text) - len, "standby=^"Loading Microsoft® Windows® Media Player components...^"^n")
		len += format(file_text[len], str_size(file_text) - len, "type=^"application/x-oleobject^">^n")
		len += format(file_text[len], str_size(file_text) - len, "<PARAM NAME=^"AutoStart^" VALUE=^"True^">^n")
		len += format(file_text[len], str_size(file_text) - len, "<PARAM NAME=^"FileName^" VALUE=^"[MEDIA_URL]^">^n")
		len += format(file_text[len], str_size(file_text) - len, "<PARAM NAME=^"ShowControls^" VALUE=^"True^">^n")
		len += format(file_text[len], str_size(file_text) - len, "<PARAM NAME=^"ShowStatusBar^" VALUE=^"False^">^n")
		len += format(file_text[len], str_size(file_text) - len, "<PARAM NAME=^"AutoRewind^" VALUE=^"True^">^n")
		len += format(file_text[len], str_size(file_text) - len, "<EMBED type=^"application/x-mplayer2^" pluginspage=^"http://www.microsoft.com/Windows/MediaPlayer/^"^n")
		len += format(file_text[len], str_size(file_text) - len, "SRC=^"[MEDIA_URL]^"^n")
		len += format(file_text[len], str_size(file_text) - len, "name=^"MediaPlayer1^"^n")
		len += format(file_text[len], str_size(file_text) - len, "autostart=1^n")
		len += format(file_text[len], str_size(file_text) - len, "showcontrols=1^n")
		len += format(file_text[len], str_size(file_text) - len, "autorewind=^"True^"^n")
		len += format(file_text[len], str_size(file_text) - len, "showstatusbar=^"False^">^n")
		len += format(file_text[len], str_size(file_text) - len, "</EMBED></OBJECT></body></pre></html>^n")
		
		write_file(g_media_player, file_text)
		log_amx("Created default media player.")
	}
	
	static file[STR_SIZE_MED]
	len = 0
	
	format(file, str_size(file), "%s/%s", configs_dir, g_media_list_filename)
	if(!file_exists(file))
	{
		len = format(file_text, str_size(file_text), "; %s Media List^n", PLUGIN_NAME)
		len += format(file_text[len], str_size(file_text) - len, "; Max string size:^n")
		len += format(file_text[len], str_size(file_text) - len, "; Group Name %d^n", sizeof(g_group_names[]))
		len += format(file_text[len], str_size(file_text) - len, "; Media Name %d^n", sizeof(g_media_names[][]))
		len += format(file_text[len], str_size(file_text) - len, "; Media URL  %d^n^n", sizeof(g_media_urls[][]))
		
		write_file(file, file_text)
		log_amx("Created media list file.")
	}

	static text[STR_SIZE_XXL]
	static left[STR_SIZE_MED]
	static right[STR_SIZE_LRG]
	
	new bool:brackets_open
	
	new line
	new length
	new group
	
	while(read_file(file, line++, text, str_size(text), length))
	{
		trim(text)
		if(!length || text[0] == ';')
			continue
		
		strbreak(text, left, str_size(left), right, str_size(right))
		
		replace_all(left, str_size(left), "^"", "")
		replace_all(right, str_size(right), "^"", "")
		
		if(brackets_open)
		{
			if(equal(text, "}"))
			{
				brackets_open = false
				continue
			}
			
			group = g_numofgroup - 1
			
			if(g_numofmedia[group] > MAX_MEDIA)
			{
				 log_amx("Max media reached")
				 break
			}
	
			if(strlen(left) > 0 && strlen(right) > 0)
			{
				replace_all(right, str_size(right), " ", "%20")
				copy(g_media_names[group][g_numofmedia[group]], str_size(g_media_names[][]), left)
				copy(g_media_urls[group][g_numofmedia[group]], str_size(g_media_urls[][]), right)
				g_numofmedia[group]++
			}
		}
		
		if(strlen(left) > 0 && equal(right, "{"))
		{
			if(g_numofgroup > MAX_GROUPS)
			{
				log_amx("Max groups reached")
				break
			}
			
			brackets_open = true
			copy(g_group_names[g_numofgroup++], str_size(g_group_names[]), left)
		}
	}
}
