<?php


/*

!pbss
!pbsay
!pbload

!pbrestart
!pbupdate
!pbver
!pbbanlist
!pbunban
!pbbanguid

UpdBanFile


*/

$punkbuster_object = new punkbuster_main();

$mod->registerCommand("pbupdate",  false, "command_update", $punkbuster_object);
$mod->registerCommand("pbrestart", false, "command_restart", $punkbuster_object);
$mod->registerCommand("pbver", false, "command_ver", $punkbuster_object);
$mod->registerCommand("pbbanlist", false, "command_banList", $punkbuster_object);
$mod->registerCommand("pbunban", "#^pbunban \d+$#i", "command_unban", $punkbuster_object);
$mod->registerCommand("pbclearbans", false, "command_clearbans", $punkbuster_object);
$mod->registerCommand("pbbanguid", "#^pbbanguid [0-9a-z]+ ?(.*?)$#i", "command_banGuid", $punkbuster_object);
$mod->registerCommand("pbgetss", "#^pbgetss (.+?)$#i", "command_getss", $punkbuster_object);
$mod->registerCommand("pbload", "#^pbload(.*?)$#i", "command_load", $punkbuster_object);


$mod->registerEvent("serverRestart", "event_serverRestart", $punkbuster_object);

class punkbuster_main {

    private $mod = false;
    private $players = false;
    private $logging = false;
    private $disabled = false;
    private $rcon = false;

    public function __construct() {
        $this->mod     = & $GLOBALS['mod'];
        $this->players = & $GLOBALS['players'];
        $this->logging = & $GLOBALS['logging'];
		$this->rcon    = & $GLOBALS['rcon'];

        $this->checkEnabled();
    }


    public function event_serverRestart() {
        $this->checkEnabled();
    }


    private function pb_update() {
        $return = $this->rcon->rcon("pb_sv_update");
        $this->logging->write(MOD_NOTICE, "Punkbuster: Update command executed (pb_sv_update)");
    }

    private function pb_ver() {
        $return = $this->rcon->rcon("pb_sv_ver");
        $pattern = '#\((v.*?) \| (A.*?) (C.*?)\)#i';
        preg_match($pattern, $return, $subpatterns);
        return array($subpatterns[1], $subpatterns[2], $subpatterns[3]);
    }

    private function pb_restart() {
        $return = $this->rcon->rcon("pb_sv_restart");
        $this->logging->write(MOD_NOTICE, "Punkbuster: Restart command executed (pb_sv_restart)");
    }

    private function pb_clearBans() {
        //pb_sv_BanEmpty

        $return = $this->rcon->rcon("pb_sv_BanEmpty");
        $this->logging->write(MOD_NOTICE, "Punkbuster: Banlist was cleared (pb_sv_BanEmpty)");

    }

    private function pb_updateBanFile() {
        //pb_sv_UpdBanFile

        $return = $this->rcon->rcon("pb_sv_UpdBanFile");
        $this->logging->write(MOD_NOTICE, "Punkbuster: BanFile was updated (pb_sv_UpdBanFile)");
    }

    private function pb_getBanList($search = "", &$entries = NULL, &$found = NULL) {
        $return = $this->rcon->rcon("pb_sv_banList \"" . $search . "\"");
        preg_match('#.*?: End of Ban List \((\d+) of (\d+) displayed\)#', $return, $subpatterns);
        $entries = $subpatterns[2];
        $found = $subpatterns[1];
        $return = substr($return, 0, 1e4);
        $lines = explode("\n", $return);
        $bans = array();
        //PunkBuster Server: 2   c90dc162f133749cec0cb632e5e01337 {10/1337} "FN! manu" "192.168.2.21:28961" haha HUHU
        $pattern = '#^.*?: (\d+)\s+([a-f0-9]+) \{(\d+)/(-?\d+)\} "(.*?)" "(.*?)"\s?(.*?)\s*$#i';
        foreach ($lines as $line) {
            if (preg_match($pattern, $line, $subpatterns)) {
                $bans[] = array(
                    "id" => $subpatterns[1],
                    "guid" => $subpatterns[2],
                    "minuteselapsed" => $subpatterns[3],
                    "banduration" => $subpatterns[4],
                    "name" => $subpatterns[5],
                    "ip" => $subpatterns[6],
                    "reason" => $subpatterns[7],
                );
            }
        }
        return $bans;

    }

    private function pb_unban($id) {
        $result = $this->rcon->rcon("pb_sv_unban $id");
        $this->logging->write(MOD_NOTICE, "Punkbuster: Deleting ban $id (pb_sv_unban)");
        return (stripos($result, "has been Unbanned") !== false) ? true : false;
    }

    private function pb_banGuid($guid, $name = "???", $ip = "???", $reason = "") {
        $return = $this->rcon->rcon("pb_sv_banguid $guid \"$name\" \"$ip\" \"$reason\"");
        return (stripos($return, "Ban Added to Ban List") !== false) ? true : false;
    }

    private function pb_getSS($search) {
        $result = $this->rcon->rcon("pb_sv_getss $search");
	    $pattern = '#.*?: (\d+) Screenshot Requested#i';
	    preg_match($pattern, $result, $subpatterns);
	    return $subpatterns[1];
    }

    private function pb_load ($file = "") {
        $result = $this->rcon->rcon("pb_sv_load $file");
        $pattern = '#.*?: file not found: (.*?)\s*#';
        if (empty($result)) {
            return true;
        }
        elseif (preg_match($pattern, $result, $subpatterns)) {
            return "File not found";
        }
        else {
            return "Unknown error";
        }
    }



    public function command_update($guid, $parameters) {
        if ($this->disabled) return false;
        $this->pb_update();
        $this->players[$guid]->say($this->mod->getLngString("punkbuster_updatestarted"));
    }

    public function command_restart($guid, $parameters) {
        if ($this->disabled) return false;
        $this->pb_restart();
        $this->players[$guid]->say($this->mod->getLngString("punkbuster_restart"));
    }

    public function command_ver($guid, $parameters) {
        if ($this->disabled) return false;
        $version = $this->pb_ver();
        $this->players[$guid]->say($this->mod->getLngString("punkbuster_version", array("{0}", "{1}", "{2}"), $version));
    }

    public function command_banList($guid, $parameters) {
        if ($this->disabled) return false;
        $search = implode(" ", $parameters);
        $bans = $this->pb_getBanList($search, $entries, $found);
        if ($found > 5) {
            $this->players[$guid]->say($this->mod->getLngString("punkbuster_toomuchresults"));
        }
        else {
            $this->players[$guid]->say($this->mod->getLngString("punkbuster_bansfound", array("<FOUND>", "<TOTAL>"), array($found, $entries)));
            foreach ($bans as $ban) {
                $search = array("<ID>", "<GUID>", "<NAME>", "<REASON>", "<LEFT>");
                $replace = array(
                    str_pad($ban["id"], 4, " ", STR_PAD_LEFT),
                    substr($ban["guid"], 0, 6),
                    $ban["name"],
                    $ban["reason"],
                    (($ban["banduration"] > -1) ? (($ban["banduration"] - $ban["minuteselapsed"]) . "min") : $this->mod->getLngString("punkbuster_unlimited")),
                );
                $str = $this->mod->getLngString("punkbuster_ban", $search, $replace);
                $this->players[$guid]->say($str);
            }
        }
    }

    public function command_unban($guid, $parameters) {
        if ($this->disabled) return false;
        if ($this->pb_unban($parameters[0])) {
            $this->players[$guid]->say($this->mod->getLngString("punkbuster_unbansuccess"));
            $this->pb_updateBanFile();
        }
        else {
            $this->players[$guid]->say($this->mod->getLngString("punkbuster_unbanfailed"));
        }
    }

    public function command_clearbans ($guid, $parameters) {
        if ($this->disabled) return false;
        $this->pb_clearBans();
        $this->players[$guid]->say($this->mod->getLngString("punkbuster_banscleared"));
        $this->pb_updateBanFile();
    }

    public function command_banGuid($guid, $parameters) {
        if ($this->disabled) return false;
        $banguid = $parameters[0];
        $name = (isset($parameters[1])) ? $parameters[1] : "???";
        $ip = (isset($parameters[2])) ? $parameters[2] : "???";
        $reason = (isset($parameters[3])) ? $parameters[3] : "";
        if ($this->pb_banGuid($banguid, $name, $ip, $reason)) {
            $this->players[$guid]->say($this->mod->getLngString("punkbuster_banguidsuccess"));
            $this->pb_updateBanFile();
        }
        else {
            $this->players[$guid]->say($this->mod->getLngString("punkbuster_banguidfailed"));
        }
    }

    public function command_getss($guid, $parameters) {
        $player = implode($parameters, " ");

        $toss = $this->mod->findPlayerGuid($player);

		if (!$toss) {
			$this->players[$guid]->say($this->mod->getLngString("playerNotFound", array("<SEARCH>"), array($player)));
		}
		else {
		    $requested = $this->pb_getSS($this->players[$toss]->getPbid());
		    $this->players[$guid]->say($this->mod->getLngString("punkbuster_ssrequested",array("<REQUESTED>", "<PLAYER_NAME>"), array($requested, $this->players[$toss]->getName())));
		}
    }

    public function command_load($guid, $parameters) {
        $file = implode($parameters);
        $result = $this->pb_load($file);
        if ($result === true) {
            $this->players[$guid]->say($this->mod->getLngString("punkbuster_loadsuccess"));
        }
        else {
            $this->players[$guid]->say($this->mod->getLngString("punkbuster_loaderror", "<ERROR>", $result));
        }
    }



    private function checkEnabled() {
        $enabled = $this->mod->rconGetDvar("sv_punkbuster");
        if (!$enabled) {
            $this->logging->write(MOD_WARNING, "Punkbuster: PB is disabled on this server (sv_punkbuster = 0), please enable it before using this plugin");
            $this->disabled = true;
        }
        else {
            $this->disabled = false;
        }
    }

}