<?php

class parser {
	private $logfile = false;
	private $parsedloglines = 0;
	private $parsedbytes = 0;
	private $lastparsed = 0;
	private $timestamptype = "relative";
	protected $logpos = false;

	public function __construct($logfile, &$success) {
		if (!is_readable($logfile)) {
			$success = false;
			return;
		}
		$this->logfile = $logfile;
		$this->logpos = filesize($this->logfile);

		$success = true;
	}

	public function getNewLines() {
	    //clearstatcache();
	    if (filesize($this->logfile) < $this->logpos) {
	        //Return pointer if log file was deleted and recreated
	        $this->logpos = 0;
	        $GLOBALS['logging']->write(MOD_WARNING, "Filepointer was bigger than filesize");
	    }

		$fp = fopen($this->logfile, "r");
		fseek($fp, $this->logpos, SEEK_SET);

		$newlines = array();


		while (!feof($fp)) {
			$get = fgets($fp);
			if ($get === false) {
				break;
			}
			$this->logpos += strlen($get);
			$newlines[] = $get;
		}

		fclose($fp);

		return $newlines;
	}

	public function parseLine($line) {
		$pattern_abs = '|^\s*(\d+) |';
		$pattern_rel = '|^\s*(\d+):(\d{2}) |';

		if (preg_match($pattern_rel, $line, $subpatterns)) {
            $this->timestamptype = "relative";
            $timestamp = 60 * $subpatterns[1] + $subpatterns[2];
		}
		elseif (preg_match($pattern_abs, $line, $subpatterns)) {
            $this->timestamptype = "absolute";
            $timestamp = $subpatterns[1];
		}
		else {
		    return false;
		}


        $lasttime = $this->lastparsed;
        $thistime = $subpatterns[1] = $timestamp;

		$this->lastparsed = $subpatterns[1];
		$this->parsedloglines ++;
		$this->parsedbytes += strlen($line);

		$line = trim(str_replace($subpatterns[0], "", $line));

		$action = $this->getAction($line);

		return array(
			"timestamp" => $this->lastparsed,
			"line" => $line,
			"action" => $action,
			"parsed" => $this->parseParts($line, $action),
		);
	}

	private function getAction($line) {
		$actions = array(
			"damage" => "D;",
			"kill" => "K;",
			"join" => "J;",
			"quit" => "Q;",
			"say" => "say;",
			"sayteam" => "sayteam;",
			"weapon" => "Weapon;",
			"nextmap" => "InitGame:",
			"exitmap" => "ShutdownGame:",
			"mapend" => "ExitLevel: executed",
			"vehicledamage" => "VD;",
			"actordamage" => "AD;",
			"jointeam" => "JT;",
			"tie" => "T;",
			"win" => "W;",
			"loss" => "L;",
			"flagcaptured" => "FC;",
			"flagtaken" => "FT;",
			"flagreturned" => "FR;",
			"hqcaptures" => "RC;",
			"hqdestroyed" => "RD;",
			"bombplanted" => "BP;",
			"bombdefused" => "BD;",
			"action" => "A;"
		);
		foreach ($actions as $key => $value) {
			if (strpos($line, $value) === 0) {
				return $key;
			}
		}
		return "unknown";
	}

	private function parseParts($line, $action) {
		switch ($action) {
			case "damage":
			case "weapon":
			case "kill":
			case "join":
			case "quit":
			case "vehicledamage":
			case "actordamage":
			case "jointeam":
			case "tie":
			case "win":
			case "loss":
			case "flagcaptured":
			case "flagtaken":
			case "flagreturned":
			case "hqcaptures":
			case "hqdestroyed":
			case "bombplanted":
			case "bombdefused":
			case "action":
				$parts = explode(";", $line);
				array_shift($parts);
				return $parts;

			case "say":
			case "sayteam";
				$parts = explode(";", $line, 5);
				array_shift($parts);
				if ($parts[3]{0} == chr(21)) {
					$parts[3] = substr($parts[3], 1);
				}
				return $parts;

			case "mapend":
			case "exitmap":
				return false;

			case "nextmap":
				$explode = explode("\\", $line);
				$parts = array();
				for($i = 1; $i < count($explode); $i += 2) {
					$parts[$explode[$i]] = $explode[$i + 1];
				}
				return $parts;

			default:
				return false;
		}
	}

	public function getLastParsedTimeStamp() {
		return $this->lastparsed;
	}

	public function getTimeStampType() {
	    return $this->timestamptype;
	}

	public function getParsedLogLines() {
	    return $this->parsedloglines;
	}

	public function getParsedBytes() {
	    return $this->parsedbytes;
	}
}