<?php


/*

enabled = 1
type = 1 // 1=Maps werden vorgeschlagen; // 2=MW2-Modus, nur !skip is möglich
maps = ""
mapcount = 4
duration = 300
announce = 45
notlastmaps = 3
votestoskip = 5% //Absolute Anzahl der Spieler oder prozentualer Anteil (wenn % verwendet wird)
gametypes
notlastgt = 1

*/


$mod->setDefaultCV("mapvote", "enabled", 0);
$mod->setDefaultCV("mapvote", "type", 2);
$mod->setDefaultCV("mapvote", "mapcount", 3);
$mod->setDefaultCV("mapvote", "duration", 300);
$mod->setDefaultCV("mapvote", "announce", 90);
$mod->setDefaultCV("mapvote", "maps", "<maps.cfg>");
$mod->setDefaultCV("mapvote", "gametypes", "dm");
$mod->setDefaultCV("mapvote", "notlastmaps", 3);
$mod->setDefaultCV("mapvote", "notlastgt", 1);
$mod->setDefaultCV("mapvote", "votestoskip", "50%");



$mapvote = new mapvote();

$mod->registerEvent("nextMap", "event_nextMap", $mapvote);
$mod->registerEvent("everyTime", "event_everyTime", $mapvote);
$mod->registerEvent("playerSay", "event_playerSay", $mapvote);

$mod->registerCommand("skip", false, "command_skip", $mapvote);
$mod->registerCommand("vmap", '|vmap \d+|i', "command_vmap", $mapvote);

class mapvote {
    private $mod;
    private $players;
    private $logging;
    private $maps = array();
    private $lastmaps = array();
    private $chosen = array();
    private $start = 0;
    private $lastAnnounce = 0;
    private $voteinprogress = false;
    private $skips = array();
    private $gametypes = array();
    private $voters = array();
    private $votes = array();

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

        $this->readConfig();

        list($this->lastmaps[]) = $this->mod->getLastMaps(1);

        if (!$this->mod->getCV("mapvote", "enabled")) return;

        if ($this->mod->getCV("mapvote", "type") == 2) {
            $this->announceSkipPossible();
        }
    }

    private function readConfig() {
        if ($this->mod->getCV("randommapcycle", "enabled") && $this->mod->getCV("mapvote", "enabled")) {
            $this->logging->write(MOD_WARNING, "Mapvote: Randommapcycle is activated; you should only use either randommapcycle or mapvote but not both");
        }
        if ($this->mod->getCV("mapvote", "maps") == "<maps.cfg>") {
            $this->maps = $this->mod->getMaps();
        }
        else {
            $this->maps = explode(",", strtolower($this->mod->getCV("mapvote", "maps")));
        }
        $this->gametypes = explode(",", strtolower($this->mod->getCV("mapvote", "gametypes")));
    }

    public function event_nextMap() {
        if (!$this->mod->getCV("mapvote", "enabled")) return;

        $this->readConfig();

        $lastmaps = $this->mod->getLastMaps(2);

        if ($lastmaps[1] == $lastmaps[0]) return;

        $this->lastmaps[] = $lastmaps[0];

        $this->voteinprogress = false;

		while (count($this->lastmaps) > $this->mod->getCV("mapvote", "notlastmaps")) {
			array_shift($this->lastmaps);
		}
		$this->lastmaps = array_merge($this->lastmaps);

		if ($this->mod->getCV("mapvote", "type") == 2) {
		    $this->announceSkipPossible();
		}
		else {
		    $this->startVote();
		}

    }

    public function event_playerSay($parameters) {
        list($guid, $msg, $executed) = $parameters;

        if (!$this->mod->getCV("mapvote", "enabled")) return;

        if ($executed) return;

        if ($this->mod->getCV("mapvote", "type") == 2 && strtolower(trim($this->mod->removeColor($msg))) == "skip") {
            $this->mod->executeCommand($this->mod->getCV("main", "prefix")."skip", $guid, $executed);
        }
        $msg = explode(" ", $msg);
        if ($this->mod->getCV("mapvote", "type") == 1 && strtolower(trim($this->mod->removeColor($msg[0]))) == "vmap") {
            if (is_numeric($msg[1])) {
                $this->mod->executeCommand($this->mod->getCV("main", "prefix")."vmap ".$msg[1], $guid, $executed);
            }
        }
    }


    private function startVote() {
        $this->chooseMap($this->mod->getCV("mapvote", "mapcount"));


        $this->start = time();
        $this->voteinprogress = true;
        $this->votes = array_fill(0, $this->mod->getCV("mapvote", "mapcount"), 0);
        $this->voters = array();

        $this->lastAnnounce = time() - $this->mod->getCV("mapvote", "announce") + 20;
    }

    private function announceVote() {
        $this->lastAnnounce = time();

        $mapstr = array();
        foreach ($this->chosen as $id => $map) {
            $mapstr[] = $this->mod->getLngString("mapvoteList", array("<ID>", "<MAP>", "<GAMETYPE>"), array($id + 1, $this->mod->getLongMapName($map["map"]), $this->mod->getLongGametype($map["gametype"])));
        }
        $mapstr = implode("\n", $mapstr);

        $this->mod->rconSay($this->mod->getLngString("mapvotevoteformap") . "\n$mapstr");
    }

    private function endVote() {
        $this->voteinprogress = false;

        arsort ($this->votes);
        reset($this->votes);
        $won = key($this->votes);
        $this->mod->rconSay($this->mod->getLngString("mapvotewonvote", array("<MAP>", "<GAMETYPE>"), array($this->mod->getLongMapName($this->chosen[$won]["map"]), $this->mod->getLongGametype($this->chosen[$won]["gametype"]))));
        $this->mod->rconSetNextMap($this->chosen[$won]["map"], $this->chosen[$won]["gametype"], false);

    }

    public function event_everyTime() {
        if (!$this->mod->getCV("mapvote", "enabled")) return;


        if ($this->mod->getCV("mapvote", "type") == 2){
            if (time() - $this->lastAnnounce >=  $this->mod->getCV("mapvote", "announce")) {
                $this->announceSkipMessage();
            }
            return;
        }

        if (!$this->voteinprogress) return;

        if (time() - $this->start >= $this->mod->getCV("mapvote", "duration")) {
            $this->endVote();
        }
        elseif (time() - $this->lastAnnounce >=  $this->mod->getCV("mapvote", "announce")) {
            $this->announceVote();
        }
    }


    private function announceSkipPossible () {
        $this->readConfig();

        $this->chooseMap(1);

		$this->mod->rconSetNextMap($this->chosen[0]["map"], $this->chosen[0]["gametype"], false);
		$this->skips = array();
		$this->lastAnnounce = time() - $this->mod->getCV("mapvote", "announce") + 20;
    }

    private function announceSkipMessage() {
        $this->mod->rconSay($this->mod->getLngString("mapvotevoteforskip", array("<MAP>", "<GAMETYPE>"), array($this->mod->getLongMapName($this->chosen[0]["map"]), $this->mod->getLongGametype($this->chosen[0]["gametype"]))));
        $this->lastAnnounce = time();
    }

    public function command_skip($guid, $parameters) {
        if (!$this->mod->getCV("mapvote", "enabled")) return;

        if ($this->mod->getCV("mapvote", "type") != 2) return;

        if (in_array($guid, $this->skips)) {
            $this->players[$guid]->say($this->mod->getLngString("mapvotealreadyvoted"));
        }
        else {
            $this->skips[] = $guid;

            if (substr(trim($this->mod->getCV("mapvote", "votestoskip")), -1) == "%") {
                $needed = round(((int) $this->mod->getCV("mapvote", "votestoskip")) / 100 * count($this->players));
            }
            else {
                $needed = (int)$this->mod->getCV("mapvote", "votestoskip");
            }

            $skippers = count($this->skips);
            $say = $this->mod->getLngString("mapvotevotedskip", array("<SKIPPERS>", "<NEEDED>", "<MAP>", "<GAMETYPE>"), array($skippers, $needed, $this->mod->getLongMapName($this->chosen[0]["map"]), $this->mod->getLongGametype($this->chosen[0]["gametype"])));
            $this->mod->rconSay($say);

            if ($skippers >= $needed) {
                $this->announceSkipPossible();
                $this->announceSkipMessage();
            }
        }
    }

    private function chooseMap($count) {
        $maps = $this->maps;
        $gametypes = $this->gametypes;

		foreach ($maps as $key => $value) {
			if (in_array($value, $this->lastmaps)) {
				unset($maps[$key]);
			}
		}


		if ($this->mod->getCV("mapvote", "notlastgt")) {
    		$current = $this->mod->getCurrentGametype();
    		foreach ($gametypes as $key => $value) {
    			if ($value == $current) {
    				unset($gametypes[$key]);
    			}
    		}
		}

		$gametypes = array_merge($gametypes);

		if (count($gametypes) == 0) $gametypes[0] = $this->mod->getCurrentGametype();

		if (count($maps) < $count) {
			$this->logging->write(MOD_WARNING, "Mapvote: Can't choose a random map because count(\$maps) < $count");
			return false;
		}

		$this->chosen = array();
		for ($i = 1; $i <= $count; $i++) {
		    $maps = array_merge($maps);
		    $rand = rand(0, count($maps) - 1);
		    $rand2 = rand(0, count($gametypes) - 1);
		    $this->chosen[] = array("map" => $maps[$rand], "gametype" => $gametypes[$rand2]);
		    unset($maps[$rand]);
		}
		return true;
    }

    public function command_vmap($guid, $parameters) {
        if (!$this->mod->getCV("mapvote", "enabled")) return;

        if ($this->mod->getCV("mapvote", "type") != 1) return;

        $map = $parameters[0] - 1;

        if (!$this->voteinprogress) return;
        if (!array_key_exists($map, $this->chosen)) return;
        if (in_array($guid, $this->voters)) return;

        $this->voters[] = $guid;
        $this->votes[$map] ++;

        $str = $this->mod->getLngString("mapvotevoted", array("<MAP>", "<GAMETYPE>"), array($this->mod->getLongMapName($this->chosen[$map]["map"]), $this->mod->getLongGametype($this->chosen[$map]["gametype"])));
        $this->players[$guid]->say($str);

    }
}


?>