/*
	PostNuke Wasteland Permissionlibrary
	Date: 14.12.2011
	Author: NeoPhoenix
*/

#if defined lib_PERM_included
	#endinput
#else
	#define lib_PERM_included
#endif
#define perm:: perm_

/*
	Adminpermissions
	native perm::GetAdminGroupIdByShortcut(shortcut);
	native perm::GetAdminPermShortcutById(perm_id);
	native perm::GetAdminPermIdByShortcut(shortcut);
	native bool:perm::HasPlayerAdminPermission(playerid,scut);
	native perm::ChangePlayerAdmPermission(playerid,scut,bool:add=false,bool:_save=true,bool:_redirect=false);
	native perm::LoadPlayerAdminPermissions(playerid,bool:_display=false);
	
	Gangpermissions
	native perm::GetGangGroupIdByShortcut(shortcut);
	native perm::GetGangPermShortcutById(perm_id);
	native perm::GetGangPermIdByShortcut(shortcut);
	native bool:perm::HasPlayerGangPermission(playerid,scut);
	native perm::ChangePlayerGangPermission(playerid,scut,bool:add=false,bool:_save=true,bool:_redirect=false);
	native perm::LoadPlayerGangPermissions(playerid,bool:_display=false);	
*/

//Requires PlayerInfo structure
#include <libraries/lib_core>

forward perm::InsufficientPermissions(playerid,message[],req_scut);
public perm::InsufficientPermissions(playerid,message[],req_scut)
{
	format(string,sizeof(string),"ERROR: insufficient permissions @-> \"%s\". Required permission '%c'",message,req_scut);
	SendClientMessage(playerid,ROT,string);
	return 1;
}

#define MAX_ADMIN_GROUP_PERMISSIONS	(5)
enum admin_permgroupe {gshort,gperms[MAX_ADMIN_GROUP_PERMISSIONS]}
new admin_permission_groups[][admin_permgroupe] = {
{'h',{'c','k'}},
{'o',{'h','t','v'}},
{'a',{'o','b'}},
{'q',{'-'}}
};
new admin_permissions[] = {'c','k','t','v','b','f'};
/*
	c - Chat
	k - Kick
	t - Teleport
	v - Vehicle
	b - Ban
	f - Forenban
*/

stock perm::GetAdminGroupIdByShortcut(shortcut)
{
	for(new i; i<sizeof(admin_permission_groups); i++)
	{
		if(admin_permission_groups[i][gshort] == shortcut) return i;
	}
	return -1;
}

stock perm::GetAdminPermShortcutById(perm_id)
{
	if(perm_id >= 0 && perm_id < sizeof(admin_permissions)) return admin_permissions[perm_id];
	return '-';
}

stock perm::GetAdminPermIdByShortcut(shortcut)
{
	for(new i; i<sizeof(admin_permissions); i++)
	{
		if(admin_permissions[i] == shortcut) return i;
	}
	return -1;
}

stock bool:perm::HasPlayerAdminPermission(playerid,scut)
{
	new group_id = perm::GetAdminGroupIdByShortcut(scut);
	if(group_id != -1)
	{
		if(PlayerInfo[playerid][Admin][1] & (1<<perm_GetAdminGroupIdByShortcut(scut))) return true;
		return false;
	}
	new perm_id = perm::GetAdminPermIdByShortcut(scut);
	if(perm_id != -1)
	{
		if(PlayerInfo[playerid][Admin][0] & (1<<perm::GetAdminPermIdByShortcut(scut))) return true;
		else return false;
	}
	return false;
}

stock perm::ChangePlayerAdmPermission(playerid,scut,bool:add=false,bool:_save=true,bool:_redirect=false)
{
	new group_id = perm::GetAdminGroupIdByShortcut(scut);
	new bool:_valid = false;
	if(group_id != -1)
	{
		_valid = true;
		if(add)
		{
			if(PlayerInfo[playerid][Admin][1] & (1<<group_id)) return 0;//schon in der gruppe
			else PlayerInfo[playerid][Admin][1] = PlayerInfo[playerid][Admin][1] | (1<<group_id);
		}
		else if(!add)
		{
			if(!(PlayerInfo[playerid][Admin][1] & (1<<group_id))) return 0;//nicht in der gruppe
			PlayerInfo[playerid][Admin][1] -= (1<<group_id);
		}
		
		for(new permid; permid<MAX_ADMIN_GROUP_PERMISSIONS; permid++)
		{
			if(!(admin_permission_groups[group_id][gperms][permid] >= 'a' && admin_permission_groups[group_id][gperms][permid] <= 'z') && admin_permission_groups[group_id][gperms][permid] != '-') continue;
			if(admin_permission_groups[group_id][gperms][permid] == '-')
			{
				for(new pps; pps<sizeof(admin_permissions); pps++) 
				{
					if(add) PlayerInfo[playerid][Admin][0] = PlayerInfo[playerid][Admin][0] | (1<<pps);
					else if(!add && PlayerInfo[playerid][Admin][0] & (1<<pps)) PlayerInfo[playerid][Admin][0] -= (1<<pps);
				}
				break;
			}
			if(add) perm::ChangePlayerAdmPermission(playerid,admin_permission_groups[group_id][gperms][permid],true,_save,true);//erneuter aufruf
			else if(!add && PlayerInfo[playerid][Admin][0] & (1<<admin_permission_groups[group_id][gperms][permid])) PlayerInfo[playerid][Admin][0] -= (1<<admin_permission_groups[group_id][gperms][permid]);
		}
		if(_redirect) return 1;
	}

	new perm_id = perm::GetAdminPermIdByShortcut(scut);
	if(perm_id != -1)
	{
		_valid = true;
		if(add) 
		{
			if(PlayerInfo[playerid][Admin][0] & (1<<perm_id)) return 0;//Hat schon
			PlayerInfo[playerid][Admin][0] = PlayerInfo[playerid][Admin][0] | (1<<perm_id);
		}
		if(!add)
		{
			if(!(PlayerInfo[playerid][Admin][0] & (1<<perm_id))) return 0;//Hatte nicht
			PlayerInfo[playerid][Admin][0] -= (1<<perm_id);
		}
		if(_redirect) return 1;
	}
	
	if(_save && _valid)
	{
		format(query,sizeof(query), "SELECT code FROM pnwl_user_permissions WHERE userid='%d' AND category='admin'",PlayerInfo[playerid][PLAYER_ID]);
		mysql_query(query);
		mysql_store_result();
		new bool:_row = mysql_num_rows()>=1?true:false;
		mysql_fetch_row(string);
		if(add)
		{
			mysql_free_result();
			format(string,sizeof(string),"%s%c",string,scut);
			if(_row) format(query,sizeof(query), "UPDATE pnwl_user_permissions SET code='%s' WHERE userid='%d' AND category='admin'",string,PlayerInfo[playerid][PLAYER_ID]);
			else format(query,sizeof(query), "INSERT INTO pnwl_user_permissions (code,userid,category) VALUES ('%s','%s','admin')",string,PlayerInfo[playerid][PLAYER_ID]);			
			mysql_query(query);
			mysql_free_result();
		}
		else
		{
			mysql_free_result();
			new loop=0,
				code[30];
			for(new i; i<strlen(string); i++)
			{
				if(string[i] == scut) continue;
				code[loop] = string[i];
				loop++;
			}
			if(_row) format(query,sizeof(query), "UPDATE pnwl_user_permissions SET code='%s' WHERE userid='%d' AND category='admin'",string,PlayerInfo[playerid][PLAYER_ID]);
			else format(query,sizeof(query), "INSERT INTO pnwl_user_permissions (code,userid,category) VALUES ('%s','%s','admin')",string,PlayerInfo[playerid][PLAYER_ID]);			
			mysql_query(query);
			mysql_free_result();
		}
	}
	if(_valid) return 1;
	return 0;
}

stock perm::LoadPlayerAdminPermissions(playerid,bool:_display=false)
{
	PlayerInfo[playerid][Admin][0] = 0;
	PlayerInfo[playerid][Admin][1] = 0;
	format(string, sizeof(string), "SELECT * FROM pnwl_user_permissions WHERE userid='%d' AND category='admin'",PlayerInfo[playerid][PLAYER_ID]);
	mysql_query(string);
	mysql_store_result();
	new count_permissions = mysql_num_rows();
	if(_display)
	{
		format(string,sizeof(string),"INFO: %d permissions found [ADMIN]",count_permissions);
		SendClientMessage(playerid,GRUEN,string);
	}
	if(count_permissions >= 1)
	{
		while(mysql_retrieve_row())
		{
			mysql_fetch_field_row(query,"code");
			if(query[0])
			{
				for(new i; i<strlen(query); i++) perm::ChangePlayerAdmPermission(playerid,query[i],true,false);
				if(_display)
				{
					format(string,sizeof(string),"INFO: Admin [permissioncode] = %s",query);
					SendClientMessage(playerid,GRUEN,string);
				}
			}
		}
	}
	mysql_free_result();
	return count_permissions;
}








//////////// GANG PART /////////////////

#define MAX_GANG_GROUP_PERMISSIONS	(5)
enum gang_permgroupe {gshort,gperms[MAX_GANG_GROUP_PERMISSIONS]}
new gang_permission_groups[][gang_permgroupe] = {
{'b',{'i','r','k'}},
{'q',{'-'}}
};
new Gang_permissions[] = {'i','r','k'};
/*
	i = Einladungen
	r = Rechte ändern
	k = Rauswerfen
*/

stock perm::GetGangGroupIdByShortcut(shortcut)
{
	for(new i; i<sizeof(gang_permission_groups); i++)
	{
		if(gang_permission_groups[i][gshort] == shortcut) return i;
	}
	return -1;
}

stock perm::GetGangPermShortcutById(perm_id)
{
	if(perm_id >= 0 && perm_id < sizeof(Gang_permissions)) return Gang_permissions[perm_id];
	return '-';
}

stock perm::GetGangPermIdByShortcut(shortcut)
{
	for(new i; i<sizeof(Gang_permissions); i++)
	{
		if(Gang_permissions[i] == shortcut) return i;
	}
	return -1;
}

stock bool:perm::HasPlayerGangPermission(playerid,scut)
{
	new group_id = perm_GetGangGroupIdByShortcut(scut);
	if(group_id != -1)
	{
		if(PlayerInfo[playerid][GangP][1] & (1<<perm_GetGangGroupIdByShortcut(scut))) return true;
		return false;
	}
	new perm_id = perm_GetGangPermIdByShortcut(scut);
	if(perm_id != -1)
	{
		if(PlayerInfo[playerid][GangP][0] & (1<<perm_GetGangPermIdByShortcut(scut))) return true;
		else return false;
	}
	return false;
}

stock perm::ChangeGangPermissionStr(playerid,str[])
{
	new bool:_vorzeichen = true;
	for(new c; c<strlen(str); c++)
	{
		if(str[c] == '+')
		{
			_vorzeichen = true;
			continue;
		}
		if(str[c] == '-')
		{
			_vorzeichen = false;
			continue;
		}
		perm::ChangePlayerGangPermission(playerid,str[c],_vorzeichen);
	}
	new newcode[15];
	for(new i; i<sizeof(Gang_permissions); i++)
	{
		if(perm::HasPlayerGangPermission(playerid,Gang_permissions[i])) 
		{
			format(newcode,sizeof(newcode),"%s%c",newcode,Gang_permissions[i]);
		}
	}
	return newcode;
}

stock perm::ChangePlayerGangPermission(playerid,scut,bool:add=false,bool:_save=true,bool:_redirect=false)
{
	new group_id = perm::GetGangGroupIdByShortcut(scut);
	new bool:_valid = false;
	if(group_id != -1)
	{
		_valid = true;
		if(add)
		{
			if(PlayerInfo[playerid][GangP][1] & (1<<group_id)) return 0;
			else PlayerInfo[playerid][GangP][1] = PlayerInfo[playerid][GangP][1] | (1<<group_id);
		}
		else if(!add)
		{
			if(!(PlayerInfo[playerid][GangP][1] & (1<<group_id))) return 0;
			PlayerInfo[playerid][GangP][1] -= (1<<group_id);
		}
		
		for(new permid; permid<MAX_GANG_GROUP_PERMISSIONS; permid++)
		{
			if(!(gang_permission_groups[group_id][gperms][permid] >= 'a' && gang_permission_groups[group_id][gperms][permid] <= 'z') && gang_permission_groups[group_id][gperms][permid] != '-') continue;
			if(gang_permission_groups[group_id][gperms][permid] == '-')
			{
				for(new pps; pps<sizeof(Gang_permissions); pps++) 
				{
					if(add) PlayerInfo[playerid][GangP][0] = PlayerInfo[playerid][GangP][0] | (1<<pps);
					else if(!add && PlayerInfo[playerid][GangP][0] & (1<<pps)) PlayerInfo[playerid][GangP][0] -= (1<<pps);
				}
				break;
			}
			if(add) 
			{
				perm::ChangePlayerGangPermission(playerid,gang_permission_groups[group_id][gperms][permid],true,_save,true);				
			}
			else if(!add && PlayerInfo[playerid][GangP][0] & (1<<gang_permission_groups[group_id][gperms][permid])) 
			{
				PlayerInfo[playerid][GangP][0] -= (1<<gang_permission_groups[group_id][gperms][permid]);				
			}
		}
		if(_redirect) return 1;
	}

	new perm_id = perm::GetGangPermIdByShortcut(scut);
	if(perm::id != -1)
	{
		_valid = true;
		if(add) 
		{
			if(PlayerInfo[playerid][GangP][0] & (1<<perm::id)) return 0;//Hat schon
			PlayerInfo[playerid][GangP][0] = PlayerInfo[playerid][GangP][0] | (1<<perm::id);
		}
		if(!add)
		{
			if(!(PlayerInfo[playerid][GangP][0] & (1<<perm_id))) return 0;//Hatte nicht
			PlayerInfo[playerid][GangP][0] -= (1<<perm_id);
		}
		if(_redirect) return 1;
	}
	
	if(_save && _valid == true)
	{
		format(query,sizeof(query), "SELECT code FROM pnwl_user_permissions WHERE userid='%d' AND category='gang'",PlayerInfo[playerid][PLAYER_ID]);
		mysql_query(query);
		mysql_store_result();
		new bool:_row = mysql_num_rows()>=1?true:false;
		mysql_fetch_row(string);
		if(add)
		{
			mysql_free_result();
			format(string,sizeof(string),"%s%c",string,scut);
			if(_row) format(query,sizeof(query), "UPDATE pnwl_user_permissions SET code='%s' WHERE userid='%d' AND category='gang'",string,PlayerInfo[playerid][PLAYER_ID]);
			else format(query,sizeof(query), "INSERT INTO pnwl_user_permissions (code,userid,category) VALUES ('%s','%s','gang')",string,PlayerInfo[playerid][PLAYER_ID]);
			mysql_query(query);
			mysql_free_result();
		}
		else
		{
			mysql_free_result();
			new loop=0,
				code[30];
			for(new i; i<strlen(string); i++)
			{
				if(string[i] == scut) continue;
				code[loop] = string[i];
				loop++;
			}
			if(_row) format(query,sizeof(query), "UPDATE pnwl_user_permissions SET code='%s' WHERE userid='%d' AND category='gang'",string,PlayerInfo[playerid][PLAYER_ID]);
			else format(query,sizeof(query), "INSERT INTO pnwl_user_permissions (code,userid,category) VALUES ('%s','%s','gang')",string,PlayerInfo[playerid][PLAYER_ID]);
			mysql_query(query);
			mysql_free_result();
		}
	}
	return _valid==true?1:0;
}

stock perm::LoadPlayerGangPermissions(playerid,bool:_display=false)
{
	PlayerInfo[playerid][GangP][0] = 0;
	PlayerInfo[playerid][GangP][1] = 0;
	format(string, sizeof(string), "SELECT * FROM pnwl_user_permissions WHERE userid='%d' AND category='gang'",PlayerInfo[playerid][PLAYER_ID]);
	mysql_query(string);
	mysql_store_result();
	new count_permissions = mysql_num_rows();
	if(_display)
	{
		format(string,sizeof(string),"INFO: %d permissions found [GANG]",count_permissions);
		SendClientMessage(playerid,GRUEN,string);
	}
	if(count_permissions >= 1)
	{
		while(mysql_retrieve_row())
		{
			mysql_fetch_field_row(query,"code");
			if(query[0])
			{
				for(new i; i<strlen(query); i++) perm::ChangePlayerGangPermission(playerid,query[i],true,false);
				if(_display)
				{
					format(string,sizeof(string),"INFO: Gang [permissioncode] = %s",query);
					SendClientMessage(playerid,GRUEN,string);
				}
			}
		}
	}
	mysql_free_result();
	return count_permissions;
}